Commit 93cd857b authored by Dorota Czaplejewicz's avatar Dorota Czaplejewicz
Browse files

Merge branch 'master' into librem5-master-3

parents 2e7381e2 fc9838b1
Pipeline #4388 passed with stage
in 1 minute and 21 seconds
image: freebsd
image: freebsd/latest
packages:
- devel/automake
- devel/evdev-proto
- devel/libepoll-shim
- devel/libudev-devd
- devel/meson # implies ninja
- devel/pkgconf
- graphics/libdrm
- graphics/mesa-libs
- graphics/png
- graphics/wayland
- graphics/wayland-protocols
- multimedia/ffmpeg
- devel/gmake
- devel/json-c
- devel/libtool
- x11/libX11
- x11/libinput
- x11/libxcb
- x11/libxkbcommon
- textproc/libxslt
- x11-toolkits/pango
- devel/pkgconf
- print/texinfo
- x11/xcb-util-image
- x11/pixman
# - x11/xcb-util-errors # too recent, not in /quarterly
- x11/xcb-util-wm
- python36
- py36-setuptools
sources:
- https://github.com/swaywm/wlroots
tasks:
- setup: |
# Don't build unnecessary stuff
echo "OPTIONS_UNSET+= NLS DOCS EXAMPLES LIBWACOM" | sudo tee -a /etc/make.conf
# Note: this could probably be set in the FreeBSD base image
echo "BATCH=yes" | sudo tee -a /etc/make.conf
- ports_tree: |
# This is ugly, but fetching and extracting the whole ports tree takes a
# really-really long time...
# First we need a clean tree, and renaming is faster than deleting.
sudo mv /usr/ports /usr/ports.orig
sudo mkdir /usr/ports
# Fetch only needed ports
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/GIDs /usr/ports/GIDs
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/Keywords /usr/ports/Keywords
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/Makefile /usr/ports/Makefile
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/Mk /usr/ports/Mk
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/Templates /usr/ports/Templates
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/Tools /usr/ports/Tools
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/UIDs /usr/ports/UIDs
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/devel/libevdev /usr/ports/devel/libevdev
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/devel/libmtdev /usr/ports/devel/libmtdev
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/devel/libudev-devd /usr/ports/devel/libudev-devd
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/devel/meson /usr/ports/devel/meson
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/devel/ninja /usr/ports/devel/ninja
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/devel/py-evdev /usr/ports/devel/py-evdev
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/devel/py-six /usr/ports/devel/py-six
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/graphics/wayland-protocols /usr/ports/graphics/wayland-protocols
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/graphics/wayland /usr/ports/graphics/wayland
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/lang/python27 /usr/ports/lang/python27
sudo svnlite export --force https://svn.FreeBSD.org/ports/head/lang/python36 /usr/ports/lang/python36
- fixup_libinput: |
sudo svnlite export https://github.com/FreeBSDDesktop/freebsd-ports/branches/feature/input/devel/libepoll-shim /usr/ports/devel/libepoll-shim
sudo svnlite export https://github.com/FreeBSDDesktop/freebsd-ports/branches/feature/input/x11/libinput /usr/ports/x11/libinput
sudo svnlite export https://github.com/FreeBSDDesktop/freebsd-ports/branches/feature/input/devel/evdev-proto /usr/ports/devel/evdev-proto
sudo svnlite export https://github.com/FreeBSDDesktop/freebsd-ports/branches/feature/input/devel/py-pyudev /usr/ports/devel/py-pyudev
- ports_build: |
cd /usr/ports/graphics/wayland-protocols/ && sudo make install
cd /usr/ports/x11/libinput/ && sudo make install clean
# v4l_compat is a dependency of libinput, but the version in the ports tree
# conflicts with the new evdev-proto. It can be safely removed though.
sudo pkg remove -fy v4l_compat
cd /usr/ports/devel/evdev-proto && sudo make install clean
- fixup_epoll: |
cat << 'EOF' | sudo tee /usr/local/libdata/pkgconfig/epoll-shim.pc
prefix=/usr/local
......@@ -70,7 +32,8 @@ tasks:
Description: epoll shim implemented using kevent
Version: 0
Requires:
Libs: -L${libdir} -L${sharedlibdir} -lepoll-shim -lthr
Libs: -L${libdir} -L${sharedlibdir} -lepoll-shim
Libs.private: -pthread -lrt
Cflags: -I${includedir}
EOF
- wlroots: |
......
......@@ -4,8 +4,9 @@ root = true
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = tab
trim_trailing_whitespace = true
indent_style = tab
indent_size = 4
[*.xml]
indent_style = space
......
......@@ -5,6 +5,7 @@ bin/
test/
build/
_build/
build-*/
wayland-*-protocol.*
wlr-example.ini
rootston.ini
......@@ -78,21 +78,6 @@ Install like so:
sudo ninja -C build install
## Running the test compositor
wlroots comes with a test compositor called rootston, which demonstrates the
features of the library and is used as a testbed for the development of the
library. It may also be useful as a reference for understanding how to use
various wlroots features, but it's not considered a production-quality codebase
and is not designed for daily use.
If you followed the build instructions above the rootston executable can be
found at `./build/rootston/rootston`. To use it, refer to the example config at
[./rootston/rootston.ini.example](https://github.com/swaywm/wlroots/blob/master/rootston/rootston.ini.example)
and place a config file of your own at `rootston.ini` in the working directory
(or in an arbitrary location via `rootston -C`). Other options are available,
refer to `rootston -h`.
## Contributing
The Librem5 version of wlroots repository is structured in a particular way. The procedure is described in the [CONTRIBUTING-librem5.md](https://source.puri.sm/Librem5/wlroots/blob/librem5/CONTRIBUTING-librem5.md) file.
......
......@@ -11,6 +11,7 @@
#include <wlr/backend/interface.h>
#include <wlr/backend/libinput.h>
#include <wlr/backend/multi.h>
#include <wlr/backend/noop.h>
#include <wlr/backend/session.h>
#include <wlr/backend/wayland.h>
#include <wlr/config.h>
......@@ -133,6 +134,20 @@ static struct wlr_backend *attempt_headless_backend(
return backend;
}
static struct wlr_backend *attempt_noop_backend(struct wl_display *display) {
struct wlr_backend *backend = wlr_noop_backend_create(display);
if (backend == NULL) {
return NULL;
}
size_t outputs = parse_outputs_env("WLR_NOOP_OUTPUTS");
for (size_t i = 0; i < outputs; ++i) {
wlr_noop_add_output(backend);
}
return backend;
}
static struct wlr_backend *attempt_drm_backend(struct wl_display *display,
struct wlr_backend *backend, struct wlr_session *session,
wlr_renderer_create_func_t create_renderer_func) {
......@@ -170,6 +185,8 @@ static struct wlr_backend *attempt_backend_by_name(struct wl_display *display,
#endif
} else if (strcmp(name, "headless") == 0) {
return attempt_headless_backend(display, create_renderer_func);
} else if (strcmp(name, "noop") == 0) {
return attempt_noop_backend(display);
} else if (strcmp(name, "drm") == 0 || strcmp(name, "libinput") == 0) {
// DRM and libinput need a session
if (!*session) {
......
......@@ -172,7 +172,8 @@ static bool atomic_crtc_set_cursor(struct wlr_drm_backend *drm,
atomic_begin(crtc, &atom);
if (bo) {
set_plane_props(&atom, plane, crtc->id, get_fb_for_bo(bo), false);
uint32_t fb_id = get_fb_for_bo(bo, plane->drm_format);
set_plane_props(&atom, plane, crtc->id, fb_id, false);
} else {
atomic_add(&atom, plane->id, plane->props.fb_id, 0);
atomic_add(&atom, plane->id, plane->props.crtc_id, 0);
......
......@@ -104,7 +104,7 @@ static void session_signal(struct wl_listener *listener, void *data) {
struct wlr_drm_plane *plane = conn->crtc->cursor;
drm->iface->crtc_set_cursor(drm, conn->crtc,
(plane && plane->cursor_enabled) ? plane->cursor_bo : NULL);
(plane && plane->cursor_enabled) ? plane->surf.back : NULL);
drm->iface->crtc_move_cursor(drm, conn->crtc, conn->cursor_x,
conn->cursor_y);
......
#define _POSIX_C_SOURCE 200112L
#include <assert.h>
#include <drm_fourcc.h>
#include <drm_mode.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
......@@ -109,8 +110,8 @@ static bool init_planes(struct wlr_drm_backend *drm) {
p->id = plane->plane_id;
p->possible_crtcs = plane->possible_crtcs;
uint64_t type;
uint64_t type;
if (!get_drm_plane_props(drm->fd, p->id, &p->props) ||
!get_drm_prop(drm->fd, p->id, p->props.type, &type)) {
drmModeFreePlane(plane);
......@@ -120,6 +121,25 @@ static bool init_planes(struct wlr_drm_backend *drm) {
p->type = type;
drm->num_type_planes[type]++;
// Choose an RGB format for the plane
uint32_t rgb_format = DRM_FORMAT_INVALID;
for (size_t j = 0; j < plane->count_formats; ++j) {
uint32_t fmt = plane->formats[j];
if (fmt == DRM_FORMAT_ARGB8888) {
// Prefer formats with alpha channel
rgb_format = fmt;
break;
} else if (fmt == DRM_FORMAT_XRGB8888) {
rgb_format = fmt;
}
}
if (rgb_format == DRM_FORMAT_INVALID) {
wlr_log(WLR_ERROR, "Failed to find an RGB format for plane %zu", i);
drmModeFreePlane(plane);
goto error_planes;
}
p->drm_format = rgb_format;
drmModeFreePlane(plane);
}
......@@ -206,12 +226,6 @@ void finish_drm_resources(struct wlr_drm_backend *drm) {
}
free(crtc->gamma_table);
}
for (size_t i = 0; i < drm->num_planes; ++i) {
struct wlr_drm_plane *plane = &drm->planes[i];
if (plane->cursor_bo) {
gbm_bo_destroy(plane->cursor_bo);
}
}
free(drm->crtcs);
free(drm->planes);
......@@ -247,7 +261,7 @@ static bool drm_connector_swap_buffers(struct wlr_output *output,
if (drm->parent) {
bo = copy_drm_surface_mgpu(&plane->mgpu_surf, bo);
}
uint32_t fb_id = get_fb_for_bo(bo);
uint32_t fb_id = get_fb_for_bo(bo, plane->drm_format);
if (conn->pageflip_pending) {
wlr_log(WLR_ERROR, "Skipping pageflip on output '%s'", conn->output.name);
......@@ -366,7 +380,7 @@ static void drm_connector_start_renderer(struct wlr_drm_connector *conn) {
struct gbm_bo *bo = get_drm_surface_front(
drm->parent ? &plane->mgpu_surf : &plane->surf);
uint32_t fb_id = get_fb_for_bo(bo);
uint32_t fb_id = get_fb_for_bo(bo, plane->drm_format);
struct wlr_drm_mode *mode = (struct wlr_drm_mode *)conn->output.current_mode;
if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, &mode->drm_mode)) {
......@@ -391,6 +405,8 @@ static void attempt_enable_needs_modeset(struct wlr_drm_backend *drm) {
if (conn->state == WLR_DRM_CONN_NEEDS_MODESET &&
conn->crtc != NULL && conn->desired_mode != NULL &&
conn->desired_enabled) {
wlr_log(WLR_DEBUG, "Output %s has a desired mode and a CRTC, "
"attempting a modeset", conn->output.name);
drm_connector_set_mode(&conn->output, conn->desired_mode);
}
}
......@@ -526,7 +542,7 @@ static bool drm_connector_set_mode(struct wlr_output *output,
conn->output.name, mode->width, mode->height, mode->refresh);
if (!init_drm_plane_surfaces(conn->crtc->primary, drm,
mode->width, mode->height, GBM_FORMAT_XRGB8888)) {
mode->width, mode->height, drm->renderer.gbm_format)) {
wlr_log(WLR_ERROR, "Failed to initialize renderer for plane");
return false;
}
......@@ -550,11 +566,18 @@ bool wlr_drm_connector_add_mode(struct wlr_output *output,
const drmModeModeInfo *modeinfo) {
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
assert(modeinfo);
if (modeinfo->type != DRM_MODE_TYPE_USERDEF) {
return false;
}
struct wlr_output_mode *wlr_mode;
wl_list_for_each(wlr_mode, &conn->output.modes, link) {
struct wlr_drm_mode *mode = (struct wlr_drm_mode *)wlr_mode;
if (memcmp(&mode->drm_mode, modeinfo, sizeof(*modeinfo)) == 0) {
return true;
}
}
struct wlr_drm_mode *mode = calloc(1, sizeof(*mode));
if (!mode) {
return false;
......@@ -563,7 +586,7 @@ bool wlr_drm_connector_add_mode(struct wlr_output *output,
mode->wlr_mode.width = mode->drm_mode.hdisplay;
mode->wlr_mode.height = mode->drm_mode.vdisplay;
mode->wlr_mode.refresh = mode->drm_mode.vrefresh;
mode->wlr_mode.refresh = calculate_refresh_rate(modeinfo);
wlr_log(WLR_INFO, "Registered custom mode "
"%"PRId32"x%"PRId32"@%"PRId32,
......@@ -609,20 +632,25 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_HEIGHT, &h);
h = ret ? 64 : h;
struct wlr_drm_renderer *renderer =
drm->parent ? &drm->parent->renderer : &drm->renderer;
if (!init_drm_surface(&plane->surf, renderer, w, h,
GBM_FORMAT_ARGB8888, 0)) {
wlr_log(WLR_ERROR, "Cannot allocate cursor resources");
return false;
}
if (!drm->parent) {
if (!init_drm_surface(&plane->surf, &drm->renderer, w, h,
drm->renderer.gbm_format, GBM_BO_USE_LINEAR | GBM_BO_USE_SCANOUT)) {
wlr_log(WLR_ERROR, "Cannot allocate cursor resources");
return false;
}
} else {
if (!init_drm_surface(&plane->surf, &drm->parent->renderer, w, h,
drm->parent->renderer.gbm_format, GBM_BO_USE_LINEAR)) {
wlr_log(WLR_ERROR, "Cannot allocate cursor resources");
return false;
}
plane->cursor_bo = gbm_bo_create(drm->renderer.gbm, w, h,
GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
if (!plane->cursor_bo) {
wlr_log_errno(WLR_ERROR, "Failed to create cursor bo");
return false;
if (!init_drm_surface(&plane->mgpu_surf, &drm->renderer, w, h,
drm->renderer.gbm_format, GBM_BO_USE_LINEAR | GBM_BO_USE_SCANOUT)) {
wlr_log(WLR_ERROR, "Cannot allocate cursor resources");
return false;
}
}
}
......@@ -630,8 +658,9 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
plane->surf.height, output->transform);
struct wlr_box hotspot = { .x = hotspot_x, .y = hotspot_y };
wlr_box_transform(&hotspot, wlr_output_transform_invert(output->transform),
plane->surf.width, plane->surf.height, &hotspot);
wlr_box_transform(&hotspot, &hotspot,
wlr_output_transform_invert(output->transform),
plane->surf.width, plane->surf.height);
if (plane->cursor_hotspot_x != hotspot.x ||
plane->cursor_hotspot_y != hotspot.y) {
......@@ -668,17 +697,6 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
return false;
}
uint32_t bo_width = gbm_bo_get_width(plane->cursor_bo);
uint32_t bo_height = gbm_bo_get_height(plane->cursor_bo);
uint32_t bo_stride;
void *bo_data;
if (!gbm_bo_map(plane->cursor_bo, 0, 0, bo_width, bo_height,
GBM_BO_TRANSFER_WRITE, &bo_stride, &bo_data)) {
wlr_log_errno(WLR_ERROR, "Unable to map buffer");
return false;
}
make_drm_surface_current(&plane->surf, NULL);
struct wlr_renderer *rend = plane->surf.renderer->wlr_rend;
......@@ -693,13 +711,8 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
wlr_render_texture_with_matrix(rend, texture, matrix, 1.0);
wlr_renderer_end(rend);
wlr_renderer_read_pixels(rend, WL_SHM_FORMAT_ARGB8888, NULL, bo_stride,
plane->surf.width, plane->surf.height, 0, 0, 0, 0, bo_data);
swap_drm_surface_buffers(&plane->surf, NULL);
gbm_bo_unmap(plane->cursor_bo, bo_data);
plane->cursor_enabled = true;
}
......@@ -707,7 +720,20 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
return true; // will be committed when session is resumed
}
struct gbm_bo *bo = plane->cursor_enabled ? plane->cursor_bo : NULL;
struct gbm_bo *bo = plane->cursor_enabled ? plane->surf.back : NULL;
if (bo && drm->parent) {
bo = copy_drm_surface_mgpu(&plane->mgpu_surf, bo);
}
if (bo) {
// workaround for nouveau
// Buffers created with GBM_BO_USER_LINEAR are placed in NOUVEAU_GEM_DOMAIN_GART.
// When the bo is attached to the cursor plane it is moved to NOUVEAU_GEM_DOMAIN_VRAM.
// However, this does not wait for the render operations to complete, leaving an empty surface.
// see https://bugs.freedesktop.org/show_bug.cgi?id=109631
// The render operations can be waited for using:
glFinish();
}
bool ok = drm->iface->crtc_set_cursor(drm, crtc, bo);
if (ok) {
wlr_output_update_needs_swap(output);
......@@ -731,7 +757,7 @@ static bool drm_connector_move_cursor(struct wlr_output *output,
enum wl_output_transform transform =
wlr_output_transform_invert(output->transform);
wlr_box_transform(&box, transform, width, height, &box);
wlr_box_transform(&box, &box, transform, width, height);
if (plane != NULL) {
box.x -= plane->cursor_hotspot_x;
......@@ -776,7 +802,6 @@ static bool drm_connector_schedule_frame(struct wlr_output *output) {
if (drm->parent) {
bo = copy_drm_surface_mgpu(&plane->mgpu_surf, bo);
}
uint32_t fb_id = get_fb_for_bo(bo);
if (conn->pageflip_pending) {
wlr_log(WLR_ERROR, "Skipping pageflip on output '%s'",
......@@ -784,6 +809,7 @@ static bool drm_connector_schedule_frame(struct wlr_output *output) {
return true;
}
uint32_t fb_id = get_fb_for_bo(bo, plane->drm_format);
if (!drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) {
return false;
}
......@@ -974,13 +1000,22 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, bool *changed_outputs) {
i++;
struct wlr_output_mode *mode = conn->output.current_mode;
if (conn->state != WLR_DRM_CONN_CONNECTED || !changed_outputs[i]
|| conn->crtc == NULL) {
if (conn->state != WLR_DRM_CONN_CONNECTED || !changed_outputs[i]) {
continue;
}
if (conn->crtc == NULL) {
wlr_log(WLR_DEBUG, "Output has %s lost its CRTC",
conn->output.name);
conn->state = WLR_DRM_CONN_NEEDS_MODESET;
wlr_output_update_enabled(&conn->output, false);
conn->desired_mode = conn->output.current_mode;
wlr_output_update_mode(&conn->output, NULL);
continue;
}
if (!init_drm_plane_surfaces(conn->crtc->primary, drm,
mode->width, mode->height, GBM_FORMAT_XRGB8888)) {
mode->width, mode->height, drm->renderer.gbm_format)) {
wlr_log(WLR_ERROR, "Failed to initialize renderer for plane");
drm_connector_cleanup(conn);
break;
......@@ -992,36 +1027,43 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, bool *changed_outputs) {
}
}
static uint32_t get_possible_crtcs(int fd, uint32_t conn_id) {
drmModeConnector *conn = drmModeGetConnector(fd, conn_id);
if (!conn) {
wlr_log_errno(WLR_ERROR, "Failed to get DRM connector");
return 0;
}
static uint32_t get_possible_crtcs(int fd, drmModeRes *res,
drmModeConnector *conn, bool is_mst) {
uint32_t ret = 0;
if (conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0) {
wlr_log(WLR_ERROR, "Output is not connected");
goto error_conn;
for (int i = 0; i < conn->count_encoders; ++i) {
drmModeEncoder *enc = drmModeGetEncoder(fd, conn->encoders[i]);
if (!enc) {
continue;
}
ret |= enc->possible_crtcs;
drmModeFreeEncoder(enc);
}
drmModeEncoder *enc = NULL;
for (int i = 0; !enc && i < conn->count_encoders; ++i) {
enc = drmModeGetEncoder(fd, conn->encoders[i]);
// Sometimes DP MST connectors report no encoders, so we'll loop though
// all of the encoders of the MST type instead.
// TODO: See if there is a better solution.
if (!is_mst || ret) {
return ret;
}
if (!enc) {
wlr_log(WLR_ERROR, "Failed to get DRM encoder");
goto error_conn;
for (int i = 0; i < res->count_encoders; ++i) {
drmModeEncoder *enc = drmModeGetEncoder(fd, res->encoders[i]);
if (!enc) {
continue;
}
if (enc->encoder_type == DRM_MODE_ENCODER_DPMST) {
ret |= enc->possible_crtcs;
}
drmModeFreeEncoder(enc);
}
uint32_t ret = enc->possible_crtcs;
drmModeFreeEncoder(enc);
drmModeFreeConnector(conn);
return ret;
error_conn:
drmModeFreeConnector(conn);
return 0;
}
void scan_drm_connectors(struct wlr_drm_backend *drm) {
......@@ -1051,7 +1093,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
drmModeEncoder *curr_enc = drmModeGetEncoder(drm->fd,
drm_conn->encoder_id);
int index = -1;
ssize_t index = -1;
struct wlr_drm_connector *c, *wlr_conn = NULL;
wl_list_for_each(c, &drm->outputs, link) {
index++;
......@@ -1087,7 +1129,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
wlr_conn->old_crtc = drmModeGetCrtc(drm->fd, curr_enc->crtc_id);
}
wl_list_insert(&drm->outputs, &wlr_conn->link);
wl_list_insert(drm->outputs.prev, &wlr_conn->link);
wlr_log(WLR_INFO, "Found connector '%s'", wlr_conn->output.name);
} else {
seen[index] = true;
......@@ -1168,7 +1210,8 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
wl_list_insert(&wlr_conn->output.modes, &mode->wlr_mode.link);
}
wlr_conn->possible_crtc = get_possible_crtcs(drm->fd, wlr_conn->id);
wlr_conn->possible_crtc = get_possible_crtcs(drm->fd, res, drm_conn,
wlr_conn->props.path != 0);
if (wlr_conn->possible_crtc == 0) {
wlr_log(WLR_ERROR, "No CRTC possible for connector '%s'",
wlr_conn->output.name);
......@@ -1179,7 +1222,8 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
wlr_conn->state = WLR_DRM_CONN_NEEDS_MODESET;
new_outputs[new_outputs_len++] = wlr_conn;
} else if (wlr_conn->state == WLR_DRM_CONN_CONNECTED &&
} else if ((wlr_conn->state == WLR_DRM_CONN_CONNECTED ||
wlr_conn->state == WLR_DRM_CONN_NEEDS_MODESET) &&
drm_conn->connection != DRM_MODE_CONNECTED) {
wlr_log(WLR_INFO, "'%s' disconnected", wlr_conn->output.name);
......@@ -1192,9 +1236,11 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
drmModeFreeResources(res);
// Iterate in reverse order because we'll remove items from the list and
// still want indices to remain correct.
struct wlr_drm_connector *conn, *tmp_conn;
size_t index = wl_list_length(&drm->outputs);
wl_list_for_each_safe(conn, tmp_conn, &drm->outputs, link) {
wl_list_for_each_reverse_safe(conn, tmp_conn, &drm->outputs, link) {
index--;
if (index >= seen_len || seen[index]) {
continue;
......
......@@ -22,6 +22,7 @@ static const struct prop_info connector_info[] = {
{ "CRTC_ID", INDEX(crtc_id) },
{ "DPMS", INDEX(dpms) },
{ "EDID", INDEX(edid) },
{ "PATH", INDEX(path) },
{ "link-status", INDEX(link_status) },
#undef INDEX
};
......
......@@ -14,10 +14,6 @@
#include "backend/drm/drm.h"
#include "glapi.h"
#ifndef DRM_FORMAT_MOD_LINEAR
#define DRM_FORMAT_MOD_LINEAR 0
#endif
bool init_drm_renderer(struct wlr_drm_backend *drm,
struct wlr_drm_renderer *renderer, wlr_renderer_create_func_t create_renderer_func) {
renderer->gbm = gbm_create_device(drm->fd);
......@@ -38,10 +34,10 @@ bool init_drm_renderer(struct wlr_drm_backend *drm,
EGL_NONE,
};
renderer->gbm_format = GBM_FORMAT_ARGB8888;
renderer->wlr_rend = create_renderer_func(&renderer->egl,
EGL_PLATFORM_GBM_MESA, renderer->gbm,
config_attribs, GBM_FORMAT_ARGB8888);
config_attribs, renderer->gbm_format);
if (!renderer->wlr_rend) {
wlr_log(WLR_ERROR, "Failed to create EGL/WLR renderer");
goto error_gbm;
......@@ -234,7 +230,7 @@ struct gbm_bo *copy_drm_surface_mgpu(struct wlr_drm_surface *dest,
struct wlr_renderer *renderer = dest->renderer->wlr_rend;
wlr_renderer_begin(renderer, dest->width, dest->height);
wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 1.0 });
wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
wlr_render_texture_with_matrix(renderer, tex, mat, 1.0f);
wlr_renderer_end(renderer);
......