Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

output: introduce wlr_output_test #2097

Merged
merged 2 commits into from
Apr 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 77 additions & 55 deletions backend/drm/drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,70 @@ static bool drm_connector_attach_render(struct wlr_output *output,
return make_drm_surface_current(&conn->crtc->primary->surf, buffer_age);
}

static uint32_t strip_alpha_channel(uint32_t format) {
switch (format) {
case DRM_FORMAT_ARGB8888:
return DRM_FORMAT_XRGB8888;
default:
return DRM_FORMAT_INVALID;
}
}

static bool test_buffer(struct wlr_drm_connector *conn,
struct wlr_buffer *wlr_buffer) {
struct wlr_output *output = &conn->output;
struct wlr_drm_backend *drm = get_drm_backend_from_backend(output->backend);

if (!drm->session->active) {
return false;
}

struct wlr_drm_crtc *crtc = conn->crtc;
if (!crtc) {
return false;
}

struct wlr_dmabuf_attributes attribs;
if (!wlr_buffer_get_dmabuf(wlr_buffer, &attribs)) {
return false;
}

if (attribs.flags != 0) {
return false;
}
if (attribs.width != output->width || attribs.height != output->height) {
return false;
}

if (!wlr_drm_format_set_has(&crtc->primary->formats,
attribs.format, attribs.modifier)) {
// The format isn't supported by the plane. Try stripping the alpha
// channel, if any.
uint32_t format = strip_alpha_channel(attribs.format);
if (format != DRM_FORMAT_INVALID && wlr_drm_format_set_has(
&crtc->primary->formats, format, attribs.modifier)) {
attribs.format = format;
} else {
return false;
}
}

return true;
}

static bool drm_connector_test(struct wlr_output *output) {
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);

if ((output->pending.committed & WLR_OUTPUT_STATE_BUFFER) &&
output->pending.buffer_type == WLR_OUTPUT_STATE_BUFFER_SCANOUT) {
if (!test_buffer(conn, output->pending.buffer)) {
return false;
}
}

return true;
}

static bool drm_connector_commit_buffer(struct wlr_output *output) {
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
struct wlr_drm_backend *drm = get_drm_backend_from_backend(output->backend);
Expand Down Expand Up @@ -373,8 +437,13 @@ static bool drm_connector_commit_buffer(struct wlr_output *output) {
return false;
}
break;
case WLR_OUTPUT_STATE_BUFFER_SCANOUT:
bo = import_gbm_bo(&drm->renderer, &conn->pending_dmabuf);
case WLR_OUTPUT_STATE_BUFFER_SCANOUT:;
struct wlr_dmabuf_attributes attribs;
if (!wlr_buffer_get_dmabuf(output->pending.buffer, &attribs)) {
return false;
}

bo = import_gbm_bo(&drm->renderer, &attribs);
if (bo == NULL) {
wlr_log(WLR_ERROR, "import_gbm_bo failed");
return false;
Expand Down Expand Up @@ -455,6 +524,10 @@ static bool drm_connector_set_custom_mode(struct wlr_output *output,
static bool drm_connector_commit(struct wlr_output *output) {
struct wlr_drm_backend *drm = get_drm_backend_from_backend(output->backend);

if (!drm_connector_test(output)) {
return false;
}

if (!drm->session->active) {
return false;
}
Expand Down Expand Up @@ -501,7 +574,7 @@ static bool drm_connector_commit(struct wlr_output *output) {

static void fill_empty_gamma_table(size_t size,
uint16_t *r, uint16_t *g, uint16_t *b) {
assert(0xFFFF < UINT64_MAX / (size - 1));
assert(0xFFFF < UINT64_MAX / (size - 1));
for (uint32_t i = 0; i < size; ++i) {
uint16_t val = (uint64_t)0xffff * i / (size - 1);
r[i] = g[i] = b[i] = val;
Expand Down Expand Up @@ -1003,57 +1076,6 @@ static bool drm_connector_move_cursor(struct wlr_output *output,
return ok;
}

static uint32_t strip_alpha_channel(uint32_t format) {
switch (format) {
case DRM_FORMAT_ARGB8888:
return DRM_FORMAT_XRGB8888;
default:
return DRM_FORMAT_INVALID;
}
}

static bool drm_connector_attach_buffer(struct wlr_output *output,
struct wlr_buffer *buffer) {
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
struct wlr_drm_backend *drm = get_drm_backend_from_backend(output->backend);
if (!drm->session->active) {
return false;
}

struct wlr_drm_crtc *crtc = conn->crtc;
if (!crtc) {
return false;
}

struct wlr_dmabuf_attributes attribs;
if (!wlr_buffer_get_dmabuf(buffer, &attribs)) {
return false;
}

if (attribs.flags != 0) {
return false;
}
if (attribs.width != output->width || attribs.height != output->height) {
return false;
}

if (!wlr_drm_format_set_has(&crtc->primary->formats,
attribs.format, attribs.modifier)) {
// The format isn't supported by the plane. Try stripping the alpha
// channel, if any.
uint32_t format = strip_alpha_channel(attribs.format);
if (format != DRM_FORMAT_INVALID && wlr_drm_format_set_has(
&crtc->primary->formats, format, attribs.modifier)) {
attribs.format = format;
} else {
return false;
}
}

memcpy(&conn->pending_dmabuf, &attribs, sizeof(attribs));
return true;
}

static void drm_connector_destroy(struct wlr_output *output) {
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
drm_connector_cleanup(conn);
Expand All @@ -1068,11 +1090,11 @@ static const struct wlr_output_impl output_impl = {
.move_cursor = drm_connector_move_cursor,
.destroy = drm_connector_destroy,
.attach_render = drm_connector_attach_render,
.test = drm_connector_test,
.commit = drm_connector_commit,
.set_gamma = set_drm_connector_gamma,
.get_gamma_size = drm_connector_get_gamma_size,
.export_dmabuf = drm_connector_export_dmabuf,
.attach_buffer = drm_connector_attach_buffer,
};

bool wlr_output_is_drm(struct wlr_output *output) {
Expand Down
13 changes: 12 additions & 1 deletion backend/headless/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,25 @@ static bool output_attach_render(struct wlr_output *wlr_output,
buffer_age);
}

static bool output_commit(struct wlr_output *wlr_output) {
static bool output_test(struct wlr_output *wlr_output) {
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) {
wlr_log(WLR_DEBUG, "Cannot disable a headless output");
return false;
}

if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
}

return true;
}

static bool output_commit(struct wlr_output *wlr_output) {
if (!output_test(wlr_output)) {
return false;
}

if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
if (!output_set_custom_mode(wlr_output,
wlr_output->pending.custom_mode.width,
wlr_output->pending.custom_mode.height,
Expand Down
61 changes: 35 additions & 26 deletions backend/wayland/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,35 @@ static const struct wl_buffer_listener buffer_listener = {
.release = buffer_handle_release,
};

static struct wlr_wl_buffer *create_wl_buffer(struct wlr_wl_backend *wl,
static bool test_buffer(struct wlr_wl_backend *wl,
struct wlr_buffer *wlr_buffer,
int required_width, int required_height) {
struct wlr_dmabuf_attributes attribs;
if (!wlr_buffer_get_dmabuf(wlr_buffer, &attribs)) {
return NULL;
return false;
}

if (attribs.width != required_width || attribs.height != required_height) {
return NULL;
return false;
}

if (!wlr_drm_format_set_has(&wl->linux_dmabuf_v1_formats,
attribs.format, attribs.modifier)) {
return false;
}

return true;
}

static struct wlr_wl_buffer *create_wl_buffer(struct wlr_wl_backend *wl,
struct wlr_buffer *wlr_buffer,
int required_width, int required_height) {
if (!test_buffer(wl, wlr_buffer, required_width, required_height)) {
return NULL;
}

struct wlr_dmabuf_attributes attribs;
if (!wlr_buffer_get_dmabuf(wlr_buffer, &attribs)) {
return NULL;
}

Expand Down Expand Up @@ -180,34 +195,28 @@ static struct wlr_wl_buffer *create_wl_buffer(struct wlr_wl_backend *wl,
return buffer;
}

static bool output_attach_buffer(struct wlr_output *wlr_output,
struct wlr_buffer *wlr_buffer) {
struct wlr_wl_output *output =
get_wl_output_from_output(wlr_output);
struct wlr_wl_backend *wl = output->backend;

struct wlr_wl_buffer *buffer = create_wl_buffer(wl, wlr_buffer,
wlr_output->width, wlr_output->height);
if (buffer == NULL) {
static bool output_test(struct wlr_output *wlr_output) {
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) {
wlr_log(WLR_DEBUG, "Cannot disable a Wayland output");
return false;
}

destroy_wl_buffer(output->pending_buffer);
output->pending_buffer = buffer;
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
}

return true;
}

static bool output_commit(struct wlr_output *wlr_output) {
struct wlr_wl_output *output =
get_wl_output_from_output(wlr_output);

if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) {
wlr_log(WLR_DEBUG, "Cannot disable a Wayland output");
if (!output_test(wlr_output)) {
return false;
}

if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
if (!output_set_custom_mode(wlr_output,
wlr_output->pending.custom_mode.width,
wlr_output->pending.custom_mode.height,
Expand Down Expand Up @@ -243,10 +252,14 @@ static bool output_commit(struct wlr_output *wlr_output) {
return false;
}
break;
case WLR_OUTPUT_STATE_BUFFER_SCANOUT:
assert(output->pending_buffer != NULL);
wl_surface_attach(output->surface,
output->pending_buffer->wl_buffer, 0, 0);
case WLR_OUTPUT_STATE_BUFFER_SCANOUT:;
struct wlr_wl_buffer *buffer = create_wl_buffer(output->backend,
wlr_output->pending.buffer, wlr_output->width, wlr_output->height);
if (buffer == NULL) {
return false;
}

wl_surface_attach(output->surface, buffer->wl_buffer, 0, 0);

if (damage == NULL) {
wl_surface_damage_buffer(output->surface,
Expand All @@ -262,8 +275,6 @@ static bool output_commit(struct wlr_output *wlr_output) {
}
}
wl_surface_commit(output->surface);

output->pending_buffer = NULL;
break;
}

Expand Down Expand Up @@ -389,8 +400,6 @@ static void output_destroy(struct wlr_output *wlr_output) {
presentation_feedback_destroy(feedback);
}

destroy_wl_buffer(output->pending_buffer);

wlr_egl_destroy_surface(&output->backend->egl, output->egl_surface);
wl_egl_window_destroy(output->egl_window);
if (output->zxdg_toplevel_decoration_v1) {
Expand Down Expand Up @@ -418,7 +427,7 @@ static bool output_move_cursor(struct wlr_output *_output, int x, int y) {
static const struct wlr_output_impl output_impl = {
.destroy = output_destroy,
.attach_render = output_attach_render,
.attach_buffer = output_attach_buffer,
.test = output_test,
.commit = output_commit,
.set_cursor = output_set_cursor,
.move_cursor = output_move_cursor,
Expand Down
18 changes: 15 additions & 3 deletions backend/x11/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,28 @@ static bool output_attach_render(struct wlr_output *wlr_output,
return wlr_egl_make_current(&x11->egl, output->surf, buffer_age);
}

static bool output_test(struct wlr_output *wlr_output) {
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) {
wlr_log(WLR_DEBUG, "Cannot disable an X11 output");
return false;
}

if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
}

return true;
}

static bool output_commit(struct wlr_output *wlr_output) {
struct wlr_x11_output *output = get_x11_output_from_output(wlr_output);
struct wlr_x11_backend *x11 = output->x11;

if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) {
wlr_log(WLR_DEBUG, "Cannot disable an X11 output");
if (!output_test(wlr_output)) {
return false;
}

if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
if (!output_set_custom_mode(wlr_output,
wlr_output->pending.custom_mode.width,
wlr_output->pending.custom_mode.height,
Expand Down Expand Up @@ -152,6 +163,7 @@ static bool output_commit(struct wlr_output *wlr_output) {
static const struct wlr_output_impl output_impl = {
.destroy = output_destroy,
.attach_render = output_attach_render,
.test = output_test,
.commit = output_commit,
};

Expand Down
2 changes: 0 additions & 2 deletions include/backend/drm/drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@ struct wlr_drm_connector {
struct wl_event_source *retry_pageflip;
struct wl_list link;

// DMA-BUF to be displayed on next commit
struct wlr_dmabuf_attributes pending_dmabuf;
// Buffer submitted to the kernel but not yet displayed
struct wlr_buffer *pending_buffer;
struct gbm_bo *pending_bo;
Expand Down
1 change: 0 additions & 1 deletion include/backend/wayland.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ struct wlr_wl_output {
struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1;
struct wl_egl_window *egl_window;
EGLSurface egl_surface;
struct wlr_wl_buffer *pending_buffer;
struct wl_list presentation_feedbacks;

uint32_t enter_serial;
Expand Down
Loading