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

Commit

Permalink
Browse files Browse the repository at this point in the history
rootston: add checks before enabling direct scan-out
  • Loading branch information
emersion committed Apr 9, 2019
1 parent 783d63a commit 68b0a11
Showing 1 changed file with 93 additions and 21 deletions.
114 changes: 93 additions & 21 deletions rootston/render.c
Expand Up @@ -177,6 +177,74 @@ static void render_drag_icons(struct roots_output *output,
render_surface_iterator, &data);
}

static void count_surface_iterator(struct roots_output *output,
struct wlr_surface *surface, struct wlr_box *_box, float rotation,
void *data) {
size_t *n = data;
n++;
}

static bool scan_out_fullscreen_view(struct roots_output *output) {
struct wlr_output *wlr_output = output->wlr_output;
struct roots_desktop *desktop = output->desktop;

struct roots_seat *seat;
wl_list_for_each(seat, &desktop->server->input->seats, link) {
struct roots_drag_icon *drag_icon = seat->drag_icon;
if (drag_icon && drag_icon->wlr_drag_icon->mapped) {
return false;
}
}

if (!wl_list_empty(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY])) {
return false;
}

struct wlr_output_cursor *cursor;
wl_list_for_each(cursor, &wlr_output->cursors, link) {
if (cursor->enabled && cursor->visible &&
wlr_output->hardware_cursor != cursor) {
return false;
}
}

struct roots_view *view = output->fullscreen_view;
assert(view != NULL);
if (view->wlr_surface == NULL) {
return false;
}
size_t n_surfaces = 0;
output_view_for_each_surface(output, view,
count_surface_iterator, &n_surfaces);
if (n_surfaces > 1) {
return false;
}

#if WLR_HAS_XWAYLAND
if (view->type == ROOTS_XWAYLAND_VIEW) {
struct roots_xwayland_surface *xwayland_surface =
roots_xwayland_surface_from_view(view);
if (!wl_list_empty(&xwayland_surface->xwayland_surface->children)) {
return false;
}
}
#endif

if (view->wlr_surface->buffer == NULL) {
return false;
}

// TODO: don't rely on the resource
struct wl_resource *buffer_resource = view->wlr_surface->buffer->resource;
if (!wlr_dmabuf_v1_resource_is_buffer(buffer_resource)) {
return false;
}
struct wlr_dmabuf_v1_buffer *dmabuf_buffer =
wlr_dmabuf_v1_buffer_from_buffer_resource(buffer_resource);

return wlr_output_set_dmabuf(wlr_output, &dmabuf_buffer->attributes);
}

static void surface_send_frame_done_iterator(struct roots_output *output,
struct wlr_surface *surface, struct wlr_box *box, float rotation,
void *data) {
Expand Down Expand Up @@ -220,6 +288,22 @@ void output_render(struct roots_output *output) {

// Fullscreen views are rendered on a black background
clear_color[0] = clear_color[1] = clear_color[2] = 0;

// Check if we can scan-out the fullscreen view
static bool last_scanned_out = false;
bool scanned_out = scan_out_fullscreen_view(output);

if (scanned_out && !last_scanned_out) {
wlr_log(WLR_DEBUG, "Scanning out fullscreen view");
}
if (last_scanned_out && !scanned_out) {
wlr_log(WLR_DEBUG, "Stopping fullscreen view scan out");
}
last_scanned_out = scanned_out;

if (scanned_out) {
goto send_frame_done;
}
}

bool needs_swap;
Expand Down Expand Up @@ -257,29 +341,9 @@ void output_render(struct roots_output *output) {
wlr_renderer_clear(renderer, clear_color);
}

render_layer(output, &damage,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
render_layer(output, &damage,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);

// If a view is fullscreen on this output, render it
if (output->fullscreen_view != NULL) {
struct roots_view *view = output->fullscreen_view;

// TODO: check this is the only surface on screen
// TODO: don't rely on the resource
struct wl_resource *buffer_resource =
output->fullscreen_view->wlr_surface->buffer->resource;
if (wlr_dmabuf_v1_resource_is_buffer(buffer_resource)) {
wlr_log(WLR_ERROR, "YES it's a dmabuf");
struct wlr_dmabuf_v1_buffer *dmabuf_buffer =
wlr_dmabuf_v1_buffer_from_buffer_resource(buffer_resource);
if (wlr_output_set_dmabuf(wlr_output, &dmabuf_buffer->attributes)) {
wlr_log(WLR_ERROR, "YES scanned out!");
goto damage_finish;
}
}

render_view(output, view, &data);

// During normal rendering the xwayland window tree isn't traversed
Expand All @@ -295,12 +359,19 @@ void output_render(struct roots_output *output) {
}
#endif
} else {
// Render background and bottom layers under views
render_layer(output, &damage,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
render_layer(output, &damage,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);

// Render all views
struct roots_view *view;
wl_list_for_each_reverse(view, &desktop->views, link) {
render_view(output, view, &data);
}
// Render top layer above shell views

// Render top layer above views
render_layer(output, &damage,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
}
Expand Down Expand Up @@ -334,6 +405,7 @@ void output_render(struct roots_output *output) {
damage_finish:
pixman_region32_fini(&damage);

send_frame_done:
// Send frame done events to all surfaces
output_for_each_surface(output, surface_send_frame_done_iterator,
&now);
Expand Down

0 comments on commit 68b0a11

Please sign in to comment.