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

[WIP] linux-explicit-synchronization-v1: new protocol implementation #2070

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
18 changes: 18 additions & 0 deletions backend/drm/atomic.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <gbm.h>
#include <stdlib.h>
#include <unistd.h>
#include <wlr/util/log.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
Expand Down Expand Up @@ -158,6 +159,10 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_backend *drm,
atomic_add(atom, id, props->crtc_x, (uint64_t)x);
atomic_add(atom, id, props->crtc_y, (uint64_t)y);

if (props->in_fence_fd) {
atomic_add(atom, id, props->in_fence_fd, plane->in_fence_fd);
}

return;

error:
Expand Down Expand Up @@ -204,6 +209,15 @@ static bool atomic_crtc_commit(struct wlr_drm_backend *drm,
vrr_enabled = output->pending.adaptive_sync_enabled;
}

int *out_fence_ptr = NULL;
if (!(flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
if (crtc->out_fence_fd >= 0) {
close(crtc->out_fence_fd);
}
crtc->out_fence_fd = -1;
out_fence_ptr = &crtc->out_fence_fd;
}

if (crtc->pending_modeset) {
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
} else {
Expand Down Expand Up @@ -237,6 +251,10 @@ static bool atomic_crtc_commit(struct wlr_drm_backend *drm,
plane_disable(&atom, crtc->cursor);
}
}
if (crtc->props.out_fence_ptr && out_fence_ptr != NULL) {
atomic_add(&atom, crtc->id, crtc->props.out_fence_ptr,
(uintptr_t)out_fence_ptr);
}
} else {
plane_disable(&atom, crtc->primary);
if (crtc->cursor) {
Expand Down
63 changes: 54 additions & 9 deletions backend/drm/drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <drm_fourcc.h>
#include <drm_mode.h>
#include <errno.h>
#include <fcntl.h>
#include <gbm.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
Expand All @@ -13,6 +14,7 @@
#include <string.h>
#include <strings.h>
#include <time.h>
#include <unistd.h>
#include <wayland-server-core.h>
#include <wayland-util.h>
#include <wlr/backend/interface.h>
Expand Down Expand Up @@ -98,6 +100,7 @@ static bool add_plane(struct wlr_drm_backend *drm,
p->type = type;
p->id = drm_plane->plane_id;
p->props = *props;
p->in_fence_fd = -1;

for (size_t j = 0; j < drm_plane->count_formats; ++j) {
wlr_drm_format_set_add(&p->formats, drm_plane->formats[j],
Expand Down Expand Up @@ -166,6 +169,15 @@ static bool add_plane(struct wlr_drm_backend *drm,
return false;
}

static void destroy_plane(struct wlr_drm_plane *plane) {
if (plane == NULL) {
return;
}
close(plane->in_fence_fd);
wlr_drm_format_set_finish(&plane->formats);
free(plane);
}

static bool init_planes(struct wlr_drm_backend *drm) {
drmModePlaneRes *plane_res = drmModeGetPlaneResources(drm->fd);
if (!plane_res) {
Expand Down Expand Up @@ -270,6 +282,7 @@ bool init_drm_resources(struct wlr_drm_backend *drm) {
struct wlr_drm_crtc *crtc = &drm->crtcs[i];
crtc->id = res->crtcs[i];
crtc->legacy_crtc = drmModeGetCrtc(drm->fd, crtc->id);
crtc->out_fence_fd = -1;
get_drm_crtc_props(drm->fd, crtc->id, &crtc->props);
}

Expand Down Expand Up @@ -305,15 +318,11 @@ void finish_drm_resources(struct wlr_drm_backend *drm) {
drmModeDestroyPropertyBlob(drm->fd, crtc->gamma_lut);
}

if (crtc->primary) {
wlr_drm_format_set_finish(&crtc->primary->formats);
free(crtc->primary);
}
if (crtc->cursor) {
wlr_drm_format_set_finish(&crtc->cursor->formats);
free(crtc->cursor);
}
destroy_plane(crtc->primary);
destroy_plane(crtc->cursor);

free(crtc->overlays);
close(crtc->out_fence_fd);
}

free(drm->crtcs);
Expand Down Expand Up @@ -342,6 +351,11 @@ static bool drm_crtc_commit(struct wlr_drm_connector *conn, uint32_t flags) {
if (crtc->cursor != NULL) {
drm_fb_move(&crtc->cursor->queued_fb, &crtc->cursor->pending_fb);
}
if (crtc->out_fence_fd >= 0 &&
crtc->primary->queued_fb.type == WLR_DRM_FB_TYPE_WLR_BUFFER) {
wlr_buffer_add_out_fence(crtc->primary->queued_fb.wlr_buf,
crtc->out_fence_fd);
}
} else {
memcpy(&crtc->pending, &crtc->current, sizeof(struct wlr_drm_crtc_state));
drm_fb_clear(&crtc->primary->pending_fb);
Expand Down Expand Up @@ -481,9 +495,13 @@ static bool drm_connector_commit_buffer(struct wlr_output *output) {
}
struct wlr_drm_plane *plane = crtc->primary;

int in_fence_fd = -1;
assert(output->pending.committed & WLR_OUTPUT_STATE_BUFFER);
switch (output->pending.buffer_type) {
case WLR_OUTPUT_STATE_BUFFER_RENDER:
// TODO: multi-GPU
in_fence_fd = wlr_renderer_dup_out_fence(drm->renderer.wlr_rend);

if (!drm_fb_lock_surface(&plane->pending_fb, &plane->surf)) {
wlr_log(WLR_ERROR, "drm_fb_lock_surface failed");
return false;
Expand All @@ -498,9 +516,21 @@ static bool drm_connector_commit_buffer(struct wlr_output *output) {
&crtc->primary->formats)) {
return false;
}

if (buffer->in_fence_fd >= 0) {
in_fence_fd = fcntl(buffer->in_fence_fd, F_DUPFD_CLOEXEC);
if (in_fence_fd < 0) {
wlr_log_errno(WLR_ERROR, "dup failed");
}
}
break;
}

if (plane->in_fence_fd >= 0) {
close(plane->in_fence_fd);
}
plane->in_fence_fd = in_fence_fd;

if (!drm_crtc_page_flip(conn)) {
return false;
}
Expand Down Expand Up @@ -861,7 +891,8 @@ struct wlr_output_mode *wlr_drm_connector_add_mode(struct wlr_output *output,
static bool drm_connector_set_cursor(struct wlr_output *output,
struct wlr_texture *texture, float scale,
enum wl_output_transform transform,
int32_t hotspot_x, int32_t hotspot_y, bool update_texture) {
int32_t hotspot_x, int32_t hotspot_y, bool update_texture,
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);
struct wlr_drm_crtc *crtc = conn->crtc;
Expand Down Expand Up @@ -932,6 +963,10 @@ static bool drm_connector_set_cursor(struct wlr_output *output,

struct wlr_renderer *rend = plane->surf.renderer->wlr_rend;

if (buffer != NULL && buffer->in_fence_fd >= 0) {
wlr_renderer_wait_in_fence(rend, buffer->in_fence_fd);
}

struct wlr_box cursor_box = { .width = width, .height = height };

float matrix[9];
Expand All @@ -941,6 +976,7 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
wlr_renderer_clear(rend, (float[]){ 0.0, 0.0, 0.0, 0.0 });
wlr_render_texture_with_matrix(rend, texture, matrix, 1.0);
wlr_renderer_end(rend);
// TODO: get out fence

if (!drm_fb_lock_surface(&plane->pending_fb, &plane->surf)) {
return false;
Expand Down Expand Up @@ -1009,6 +1045,14 @@ bool drm_connector_is_cursor_visible(struct wlr_drm_connector *conn) {
conn->cursor_y + (int)plane->surf.height >= 0;
}

static int drm_connector_get_out_fence(struct wlr_output *output) {
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
if (conn->crtc == NULL) {
return -1;
}
return conn->crtc->out_fence_fd;
}

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 @@ -1027,6 +1071,7 @@ static const struct wlr_output_impl output_impl = {
.rollback_render = drm_connector_rollback_render,
.get_gamma_size = drm_connector_get_gamma_size,
.export_dmabuf = drm_connector_export_dmabuf,
.get_out_fence = drm_connector_get_out_fence,
};

bool wlr_output_is_drm(struct wlr_output *output) {
Expand Down
2 changes: 2 additions & 0 deletions backend/drm/properties.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ 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) },
{ "rotation", INDEX(rotation) },
{ "scaling mode", INDEX(scaling_mode) },
Expand All @@ -48,6 +49,7 @@ static const struct prop_info plane_info[] = {
{ "CRTC_X", INDEX(crtc_x) },
{ "CRTC_Y", INDEX(crtc_y) },
{ "FB_ID", INDEX(fb_id) },
{ "IN_FENCE_FD", INDEX(in_fence_fd) },
{ "IN_FORMATS", INDEX(in_formats) },
{ "SRC_H", INDEX(src_h) },
{ "SRC_W", INDEX(src_w) },
Expand Down
3 changes: 2 additions & 1 deletion backend/wayland/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ static void output_rollback_render(struct wlr_output *wlr_output) {
static bool output_set_cursor(struct wlr_output *wlr_output,
struct wlr_texture *texture, float scale,
enum wl_output_transform transform,
int32_t hotspot_x, int32_t hotspot_y, bool update_texture) {
int32_t hotspot_x, int32_t hotspot_y, bool update_texture,
struct wlr_buffer *buffer) {
struct wlr_wl_output *output = get_wl_output_from_output(wlr_output);
struct wlr_wl_backend *backend = output->backend;

Expand Down
4 changes: 4 additions & 0 deletions include/backend/drm/drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ struct wlr_drm_plane {
bool cursor_enabled;
int32_t cursor_hotspot_x, cursor_hotspot_y;

int in_fence_fd;

union wlr_drm_plane_props props;
};

Expand Down Expand Up @@ -71,6 +73,8 @@ struct wlr_drm_crtc {
uint32_t *overlays;

union wlr_drm_crtc_props props;

int out_fence_fd;
};

struct wlr_drm_backend {
Expand Down
2 changes: 2 additions & 0 deletions include/backend/drm/properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ union wlr_drm_crtc_props {

uint32_t active;
uint32_t mode_id;
uint32_t out_fence_ptr;
};
uint32_t props[6];
};
Expand All @@ -60,6 +61,7 @@ union wlr_drm_plane_props {
uint32_t crtc_h;
uint32_t fb_id;
uint32_t crtc_id;
uint32_t in_fence_fd;
};
uint32_t props[13];
};
Expand Down
1 change: 1 addition & 0 deletions include/render/gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct wlr_gles2_renderer {
} shaders;

uint32_t viewport_width, viewport_height;
EGLSyncKHR end_sync;
};

struct wlr_gles2_texture {
Expand Down
9 changes: 9 additions & 0 deletions include/render/sync_file.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef RENDER_SYNC_FILE_H
#define RENDER_SYNC_FILE_H

#include <stdbool.h>

bool fd_is_sync_file(int fd);
int sync_file_merge(int fd1, int fd2);

#endif
4 changes: 3 additions & 1 deletion include/wlr/interfaces/wlr_output.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
struct wlr_output_impl {
bool (*set_cursor)(struct wlr_output *output, struct wlr_texture *texture,
float scale, enum wl_output_transform transform,
int32_t hotspot_x, int32_t hotspot_y, bool update_texture);
int32_t hotspot_x, int32_t hotspot_y, bool update_texture,
struct wlr_buffer *buffer);
bool (*move_cursor)(struct wlr_output *output, int x, int y);
void (*destroy)(struct wlr_output *output);
bool (*attach_render)(struct wlr_output *output, int *buffer_age);
Expand All @@ -27,6 +28,7 @@ struct wlr_output_impl {
size_t (*get_gamma_size)(struct wlr_output *output);
bool (*export_dmabuf)(struct wlr_output *output,
struct wlr_dmabuf_attributes *attribs);
int (*get_out_fence)(struct wlr_output *output);
};

void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend,
Expand Down
12 changes: 12 additions & 0 deletions include/wlr/render/egl.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ struct wlr_egl {
PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC eglExportDMABUFImageQueryMESA;
PFNEGLEXPORTDMABUFIMAGEMESAPROC eglExportDMABUFImageMESA;
PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR;
PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR;
PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR;
PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID;
PFNEGLWAITSYNCKHRPROC eglWaitSyncKHR;
} procs;

struct wl_display *wl_display;
Expand Down Expand Up @@ -161,4 +165,12 @@ bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface,

bool wlr_egl_destroy_surface(struct wlr_egl *egl, EGLSurface surface);

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
2 changes: 2 additions & 0 deletions include/wlr/render/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ struct wlr_renderer_impl {
uint32_t *flags, uint32_t stride, uint32_t width, uint32_t height,
uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y,
void *data);
int (*dup_out_fence)(struct wlr_renderer *renderer);
bool (*wait_in_fence)(struct wlr_renderer *renderer, int fd);
struct wlr_texture *(*texture_from_pixels)(struct wlr_renderer *renderer,
enum wl_shm_format fmt, uint32_t stride, uint32_t width,
uint32_t height, const void *data);
Expand Down
11 changes: 11 additions & 0 deletions include/wlr/render/wlr_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,15 @@ bool wlr_renderer_init_wl_display(struct wlr_renderer *r,
*/
void wlr_renderer_destroy(struct wlr_renderer *renderer);

/**
* Create a new fence that will be signalled when rendering completes.
*
* This function must be called after wlr_renderer_end.
*/
int wlr_renderer_dup_out_fence(struct wlr_renderer *renderer);
/**
* Wait for a fence before executing the next rendering operations.
*/
bool wlr_renderer_wait_in_fence(struct wlr_renderer *renderer, int fd);

#endif
13 changes: 13 additions & 0 deletions include/wlr/types/wlr_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ struct wlr_buffer {
bool dropped;
size_t n_locks;

int in_fence_fd, out_fence_fd;

struct {
struct wl_signal destroy;
struct wl_signal release;
Expand Down Expand Up @@ -77,6 +79,17 @@ void wlr_buffer_unlock(struct wlr_buffer *buffer);
bool wlr_buffer_get_dmabuf(struct wlr_buffer *buffer,
struct wlr_dmabuf_attributes *attribs);

/**
* Should be called after writing to the buffer with a fence which will be
* signalled once writing is complete.
*/
void wlr_buffer_set_in_fence(struct wlr_buffer *buffer, int fd);
/**
* Should be called after reading from the buffer with a fence which will be
* signalled once reading is complete.
*/
void wlr_buffer_add_out_fence(struct wlr_buffer *buffer, int fd);

/**
* A client buffer.
*/
Expand Down
Loading