mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2024-11-21 22:52:20 +00:00
backend/drm: add explicit sync support to multi-GPU blits
This commit is contained in:
parent
3187479c07
commit
d7223eae02
@ -275,9 +275,9 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
int in_fence_fd = -1;
|
int in_fence_fd = -1;
|
||||||
if (state->base->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) {
|
if (state->wait_timeline != NULL) {
|
||||||
in_fence_fd = wlr_drm_syncobj_timeline_export_sync_file(state->base->wait_timeline,
|
in_fence_fd = wlr_drm_syncobj_timeline_export_sync_file(state->wait_timeline,
|
||||||
state->base->wait_point);
|
state->wait_point);
|
||||||
if (in_fence_fd < 0) {
|
if (in_fence_fd < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <wayland-util.h>
|
#include <wayland-util.h>
|
||||||
#include <wlr/backend/interface.h>
|
#include <wlr/backend/interface.h>
|
||||||
#include <wlr/interfaces/wlr_output.h>
|
#include <wlr/interfaces/wlr_output.h>
|
||||||
|
#include <wlr/render/drm_syncobj.h>
|
||||||
#include <wlr/render/wlr_renderer.h>
|
#include <wlr/render/wlr_renderer.h>
|
||||||
#include <wlr/util/box.h>
|
#include <wlr/util/box.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
@ -693,6 +694,7 @@ static void drm_connector_state_init(struct wlr_drm_connector_state *state,
|
|||||||
static void drm_connector_state_finish(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->primary_fb);
|
||||||
drm_fb_clear(&state->cursor_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,
|
static bool drm_connector_state_update_primary_fb(struct wlr_drm_connector *conn,
|
||||||
@ -707,6 +709,14 @@ static bool drm_connector_state_update_primary_fb(struct wlr_drm_connector *conn
|
|||||||
struct wlr_drm_plane *plane = crtc->primary;
|
struct wlr_drm_plane *plane = crtc->primary;
|
||||||
struct wlr_buffer *source_buf = state->base->buffer;
|
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;
|
struct wlr_buffer *local_buf;
|
||||||
if (drm->parent) {
|
if (drm->parent) {
|
||||||
struct wlr_drm_format format = {0};
|
struct wlr_drm_format format = {0};
|
||||||
@ -723,12 +733,23 @@ static bool drm_connector_state_update_primary_fb(struct wlr_drm_connector *conn
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
local_buf = drm_surface_blit(&plane->mgpu_surf, source_buf);
|
local_buf = drm_surface_blit(&plane->mgpu_surf, source_buf,
|
||||||
|
wait_timeline, wait_point);
|
||||||
if (local_buf == NULL) {
|
if (local_buf == NULL) {
|
||||||
return false;
|
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 {
|
} else {
|
||||||
local_buf = wlr_buffer_lock(source_buf);
|
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,
|
bool ok = drm_fb_import(&state->primary_fb, drm, local_buf,
|
||||||
@ -1088,7 +1109,7 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
local_buf = drm_surface_blit(&plane->mgpu_surf, buffer);
|
local_buf = drm_surface_blit(&plane->mgpu_surf, buffer, NULL, 0);
|
||||||
if (local_buf == NULL) {
|
if (local_buf == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1625,9 +1646,11 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
|
|||||||
output->non_desktop = non_desktop;
|
output->non_desktop = non_desktop;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: support sync timelines in multi-GPU mode
|
|
||||||
// TODO: support sync timelines with libliftoff
|
// TODO: support sync timelines with libliftoff
|
||||||
output->timeline = drm->parent == NULL && drm->iface == &atomic_iface;
|
output->timeline = drm->iface == &atomic_iface;
|
||||||
|
if (drm->parent) {
|
||||||
|
output->timeline = output->timeline && drm->mgpu_renderer.wlr_rend->features.timeline;
|
||||||
|
}
|
||||||
|
|
||||||
memset(wlr_conn->max_bpc_bounds, 0, sizeof(wlr_conn->max_bpc_bounds));
|
memset(wlr_conn->max_bpc_bounds, 0, sizeof(wlr_conn->max_bpc_bounds));
|
||||||
if (wlr_conn->props.max_bpc != 0) {
|
if (wlr_conn->props.max_bpc != 0) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <drm_fourcc.h>
|
#include <drm_fourcc.h>
|
||||||
|
#include <wlr/render/drm_syncobj.h>
|
||||||
#include <wlr/render/swapchain.h>
|
#include <wlr/render/swapchain.h>
|
||||||
#include <wlr/render/wlr_renderer.h>
|
#include <wlr/render/wlr_renderer.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
@ -46,6 +47,7 @@ void finish_drm_surface(struct wlr_drm_surface *surf) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlr_drm_syncobj_timeline_unref(surf->timeline);
|
||||||
wlr_swapchain_destroy(surf->swapchain);
|
wlr_swapchain_destroy(surf->swapchain);
|
||||||
|
|
||||||
*surf = (struct wlr_drm_surface){0};
|
*surf = (struct wlr_drm_surface){0};
|
||||||
@ -68,13 +70,24 @@ bool init_drm_surface(struct wlr_drm_surface *surf,
|
|||||||
return false;
|
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;
|
surf->renderer = renderer;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
||||||
struct wlr_buffer *buffer) {
|
struct wlr_buffer *buffer,
|
||||||
|
struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point) {
|
||||||
struct wlr_renderer *renderer = surf->renderer->wlr_rend;
|
struct wlr_renderer *renderer = surf->renderer->wlr_rend;
|
||||||
|
|
||||||
if (surf->swapchain->width != buffer->width ||
|
if (surf->swapchain->width != buffer->width ||
|
||||||
@ -95,7 +108,12 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
|||||||
goto error_tex;
|
goto error_tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, dst, NULL);
|
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);
|
||||||
if (pass == NULL) {
|
if (pass == NULL) {
|
||||||
wlr_log(WLR_ERROR, "Failed to begin render pass with multi-GPU destination buffer");
|
wlr_log(WLR_ERROR, "Failed to begin render pass with multi-GPU destination buffer");
|
||||||
goto error_dst;
|
goto error_dst;
|
||||||
@ -104,6 +122,8 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
|||||||
wlr_render_pass_add_texture(pass, &(struct wlr_render_texture_options){
|
wlr_render_pass_add_texture(pass, &(struct wlr_render_texture_options){
|
||||||
.texture = tex,
|
.texture = tex,
|
||||||
.blend_mode = WLR_RENDER_BLEND_MODE_NONE,
|
.blend_mode = WLR_RENDER_BLEND_MODE_NONE,
|
||||||
|
.wait_timeline = wait_timeline,
|
||||||
|
.wait_point = wait_point,
|
||||||
});
|
});
|
||||||
if (!wlr_render_pass_submit(pass)) {
|
if (!wlr_render_pass_submit(pass)) {
|
||||||
wlr_log(WLR_ERROR, "Failed to submit multi-GPU render pass");
|
wlr_log(WLR_ERROR, "Failed to submit multi-GPU render pass");
|
||||||
|
@ -141,6 +141,9 @@ struct wlr_drm_connector_state {
|
|||||||
struct wlr_drm_fb *primary_fb;
|
struct wlr_drm_fb *primary_fb;
|
||||||
struct wlr_drm_fb *cursor_fb;
|
struct wlr_drm_fb *cursor_fb;
|
||||||
|
|
||||||
|
struct wlr_drm_syncobj_timeline *wait_timeline;
|
||||||
|
uint64_t wait_point;
|
||||||
|
|
||||||
// used by atomic
|
// used by atomic
|
||||||
uint32_t mode_id;
|
uint32_t mode_id;
|
||||||
uint32_t gamma_lut;
|
uint32_t gamma_lut;
|
||||||
|
@ -20,6 +20,9 @@ struct wlr_drm_renderer {
|
|||||||
struct wlr_drm_surface {
|
struct wlr_drm_surface {
|
||||||
struct wlr_drm_renderer *renderer;
|
struct wlr_drm_renderer *renderer;
|
||||||
struct wlr_swapchain *swapchain;
|
struct wlr_swapchain *swapchain;
|
||||||
|
|
||||||
|
struct wlr_drm_syncobj_timeline *timeline;
|
||||||
|
uint64_t point;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool init_drm_renderer(struct wlr_drm_backend *drm,
|
bool init_drm_renderer(struct wlr_drm_backend *drm,
|
||||||
@ -32,7 +35,8 @@ bool init_drm_surface(struct wlr_drm_surface *surf,
|
|||||||
void finish_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 *drm_surface_blit(struct wlr_drm_surface *surf,
|
||||||
struct wlr_buffer *buffer);
|
struct wlr_buffer *buffer,
|
||||||
|
struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point);
|
||||||
|
|
||||||
bool drm_plane_pick_render_format(struct wlr_drm_plane *plane,
|
bool drm_plane_pick_render_format(struct wlr_drm_plane *plane,
|
||||||
struct wlr_drm_format *fmt, struct wlr_drm_renderer *renderer);
|
struct wlr_drm_format *fmt, struct wlr_drm_renderer *renderer);
|
||||||
|
Loading…
Reference in New Issue
Block a user