mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-06-13 14:32:57 -04:00
Merge branch 'capture_sync_2' into 'master'
ext_image_capture_source_v1: wait for explicit sync Closes #4064 See merge request wlroots/wlroots!5314
This commit is contained in:
commit
9cf7c7ad5c
4 changed files with 184 additions and 18 deletions
|
|
@ -12,9 +12,11 @@
|
||||||
#include <pixman.h>
|
#include <pixman.h>
|
||||||
#include <wayland-server-protocol.h>
|
#include <wayland-server-protocol.h>
|
||||||
#include <wayland-protocols/ext-image-copy-capture-v1-enum.h>
|
#include <wayland-protocols/ext-image-copy-capture-v1-enum.h>
|
||||||
|
#include <wlr/render/drm_syncobj.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
struct wlr_renderer;
|
struct wlr_renderer;
|
||||||
|
struct wlr_drm_syncobj_timeline;
|
||||||
|
|
||||||
struct wlr_ext_image_copy_capture_manager_v1 {
|
struct wlr_ext_image_copy_capture_manager_v1 {
|
||||||
struct wl_global *global;
|
struct wl_global *global;
|
||||||
|
|
@ -43,6 +45,8 @@ struct wlr_ext_image_copy_capture_session_v1 {
|
||||||
struct wl_listener source_frame;
|
struct wl_listener source_frame;
|
||||||
|
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
|
struct wlr_drm_syncobj_timeline *copy_timeline;
|
||||||
|
uint64_t copy_point;
|
||||||
} WLR_PRIVATE;
|
} WLR_PRIVATE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -58,6 +62,10 @@ struct wlr_ext_image_copy_capture_frame_v1 {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wlr_ext_image_copy_capture_session_v1 *session;
|
struct wlr_ext_image_copy_capture_session_v1 *session;
|
||||||
|
enum wl_output_transform pending_transform;
|
||||||
|
struct timespec pending_presentation_time;
|
||||||
|
bool copy_waiter_initialized;
|
||||||
|
struct wlr_drm_syncobj_timeline_waiter copy_waiter;
|
||||||
} WLR_PRIVATE;
|
} WLR_PRIVATE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -71,6 +79,17 @@ struct wlr_ext_image_copy_capture_manager_v1 *wlr_ext_image_copy_capture_manager
|
||||||
*/
|
*/
|
||||||
void wlr_ext_image_copy_capture_frame_v1_ready(struct wlr_ext_image_copy_capture_frame_v1 *frame,
|
void wlr_ext_image_copy_capture_frame_v1_ready(struct wlr_ext_image_copy_capture_frame_v1 *frame,
|
||||||
enum wl_output_transform transform, const struct timespec *presentation_time);
|
enum wl_output_transform transform, const struct timespec *presentation_time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the client that the frame is ready, when timeline point is signalled.
|
||||||
|
*
|
||||||
|
* This function causes the frame destruction, and may destroy it synchronously.
|
||||||
|
*/
|
||||||
|
bool wlr_ext_image_copy_capture_frame_v1_ready_deferred(
|
||||||
|
struct wlr_ext_image_copy_capture_frame_v1 *frame,
|
||||||
|
enum wl_output_transform transform, const struct timespec *presentation_time,
|
||||||
|
struct wlr_drm_syncobj_timeline *timeline, uint64_t point);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify the client that the frame has failed.
|
* Notify the client that the frame has failed.
|
||||||
*
|
*
|
||||||
|
|
@ -80,8 +99,14 @@ void wlr_ext_image_copy_capture_frame_v1_fail(struct wlr_ext_image_copy_capture_
|
||||||
enum ext_image_copy_capture_frame_v1_failure_reason reason);
|
enum ext_image_copy_capture_frame_v1_failure_reason reason);
|
||||||
/**
|
/**
|
||||||
* Copy a struct wlr_buffer into the client-provided buffer for the frame.
|
* Copy a struct wlr_buffer into the client-provided buffer for the frame.
|
||||||
|
*
|
||||||
|
* If the caller obtains a timeline point through `out_copy_timeline` and
|
||||||
|
* `out_copy_timeline`, it must wait for it to signal before sending the
|
||||||
|
* "frame ready" event to the capture client
|
||||||
*/
|
*/
|
||||||
bool wlr_ext_image_copy_capture_frame_v1_copy_buffer(struct wlr_ext_image_copy_capture_frame_v1 *frame,
|
bool wlr_ext_image_copy_capture_frame_v1_copy_buffer(struct wlr_ext_image_copy_capture_frame_v1 *frame,
|
||||||
struct wlr_buffer *src, struct wlr_renderer *renderer);
|
struct wlr_buffer *src, struct wlr_renderer *renderer,
|
||||||
|
struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point,
|
||||||
|
struct wlr_drm_syncobj_timeline **out_copy_timeline, uint64_t *out_copy_point);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ struct wlr_ext_output_image_capture_source_v1_frame_event {
|
||||||
struct wlr_ext_image_capture_source_v1_frame_event base;
|
struct wlr_ext_image_capture_source_v1_frame_event base;
|
||||||
struct wlr_buffer *buffer;
|
struct wlr_buffer *buffer;
|
||||||
struct timespec when;
|
struct timespec when;
|
||||||
|
struct wlr_drm_syncobj_timeline *wait_timeline;
|
||||||
|
uint64_t wait_point;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void output_source_start(struct wlr_ext_image_capture_source_v1 *base,
|
static void output_source_start(struct wlr_ext_image_capture_source_v1 *base,
|
||||||
|
|
@ -85,10 +87,19 @@ static void output_source_copy_frame(struct wlr_ext_image_capture_source_v1 *bas
|
||||||
struct wlr_ext_output_image_capture_source_v1_frame_event *event =
|
struct wlr_ext_output_image_capture_source_v1_frame_event *event =
|
||||||
wl_container_of(base_event, event, base);
|
wl_container_of(base_event, event, base);
|
||||||
|
|
||||||
|
struct wlr_drm_syncobj_timeline *copy_timeline;
|
||||||
|
uint64_t copy_point;
|
||||||
if (wlr_ext_image_copy_capture_frame_v1_copy_buffer(frame,
|
if (wlr_ext_image_copy_capture_frame_v1_copy_buffer(frame,
|
||||||
event->buffer, source->output->renderer)) {
|
event->buffer, source->output->renderer,
|
||||||
wlr_ext_image_copy_capture_frame_v1_ready(frame,
|
event->wait_timeline, event->wait_point, ©_timeline, ©_point)) {
|
||||||
source->output->transform, &event->when);
|
if (copy_timeline != NULL) {
|
||||||
|
wlr_ext_image_copy_capture_frame_v1_ready_deferred(frame,
|
||||||
|
source->output->transform, &event->when, copy_timeline, copy_point);
|
||||||
|
wlr_drm_syncobj_timeline_unref(copy_timeline);
|
||||||
|
} else {
|
||||||
|
wlr_ext_image_copy_capture_frame_v1_ready(frame,
|
||||||
|
source->output->transform, &event->when);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,6 +163,10 @@ static void source_handle_output_commit(struct wl_listener *listener,
|
||||||
.buffer = buffer,
|
.buffer = buffer,
|
||||||
.when = event->when, // TODO: predict next presentation time instead
|
.when = event->when, // TODO: predict next presentation time instead
|
||||||
};
|
};
|
||||||
|
if (event->state->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) {
|
||||||
|
frame_event.wait_timeline = event->state->wait_timeline;
|
||||||
|
frame_event.wait_point = event->state->wait_point;
|
||||||
|
}
|
||||||
wl_signal_emit_mutable(&source->base.events.frame, &frame_event);
|
wl_signal_emit_mutable(&source->base.events.frame, &frame_event);
|
||||||
|
|
||||||
pixman_region32_fini(&full_damage);
|
pixman_region32_fini(&full_damage);
|
||||||
|
|
@ -279,6 +294,8 @@ static void output_cursor_source_copy_frame(struct wlr_ext_image_capture_source_
|
||||||
struct wlr_ext_image_copy_capture_frame_v1 *frame,
|
struct wlr_ext_image_copy_capture_frame_v1 *frame,
|
||||||
struct wlr_ext_image_capture_source_v1_frame_event *base_event) {
|
struct wlr_ext_image_capture_source_v1_frame_event *base_event) {
|
||||||
struct output_cursor_source *cursor_source = wl_container_of(base, cursor_source, base);
|
struct output_cursor_source *cursor_source = wl_container_of(base, cursor_source, base);
|
||||||
|
struct wlr_ext_output_image_capture_source_v1_frame_event *event =
|
||||||
|
wl_container_of(base_event, event, base);
|
||||||
|
|
||||||
struct wlr_buffer *src_buffer = cursor_source->output->cursor_front_buffer;
|
struct wlr_buffer *src_buffer = cursor_source->output->cursor_front_buffer;
|
||||||
if (src_buffer == NULL) {
|
if (src_buffer == NULL) {
|
||||||
|
|
@ -286,16 +303,25 @@ static void output_cursor_source_copy_frame(struct wlr_ext_image_capture_source_
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wlr_drm_syncobj_timeline *copy_timeline;
|
||||||
|
uint64_t copy_point;
|
||||||
if (!wlr_ext_image_copy_capture_frame_v1_copy_buffer(frame,
|
if (!wlr_ext_image_copy_capture_frame_v1_copy_buffer(frame,
|
||||||
src_buffer, cursor_source->output->renderer)) {
|
src_buffer, cursor_source->output->renderer,
|
||||||
|
event->wait_timeline, event->wait_point, ©_timeline, ©_point)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
wlr_ext_image_copy_capture_frame_v1_ready(frame,
|
if (copy_timeline != NULL) {
|
||||||
|
wlr_ext_image_copy_capture_frame_v1_ready_deferred(frame,
|
||||||
|
cursor_source->output->transform, &now, copy_timeline, copy_point);
|
||||||
|
wlr_drm_syncobj_timeline_unref(copy_timeline);
|
||||||
|
} else {
|
||||||
|
wlr_ext_image_copy_capture_frame_v1_ready(frame,
|
||||||
cursor_source->output->transform, &now);
|
cursor_source->output->transform, &now);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wlr_ext_image_capture_source_v1_interface output_cursor_source_impl = {
|
static const struct wlr_ext_image_capture_source_v1_interface output_cursor_source_impl = {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
|
|
||||||
|
#include "render/dmabuf.h"
|
||||||
|
#include "render/drm_syncobj_merger.h"
|
||||||
#include "types/wlr_output.h"
|
#include "types/wlr_output.h"
|
||||||
#include "types/wlr_scene.h"
|
#include "types/wlr_scene.h"
|
||||||
|
|
||||||
|
|
@ -30,6 +32,9 @@ struct scene_node_source_frame_event {
|
||||||
struct wlr_ext_image_capture_source_v1_frame_event base;
|
struct wlr_ext_image_capture_source_v1_frame_event base;
|
||||||
struct wlr_buffer *buffer;
|
struct wlr_buffer *buffer;
|
||||||
struct timespec when;
|
struct timespec when;
|
||||||
|
struct wlr_drm_syncobj_timeline *wait_timeline;
|
||||||
|
uint64_t wait_point;
|
||||||
|
struct wlr_drm_syncobj_merger *release_merger;
|
||||||
};
|
};
|
||||||
|
|
||||||
static size_t last_output_num = 0;
|
static size_t last_output_num = 0;
|
||||||
|
|
@ -148,10 +153,23 @@ static void source_copy_frame(struct wlr_ext_image_capture_source_v1 *base,
|
||||||
struct scene_node_source *source = wl_container_of(base, source, base);
|
struct scene_node_source *source = wl_container_of(base, source, base);
|
||||||
struct scene_node_source_frame_event *event = wl_container_of(base_event, event, base);
|
struct scene_node_source_frame_event *event = wl_container_of(base_event, event, base);
|
||||||
|
|
||||||
|
struct wlr_drm_syncobj_timeline *copy_timeline;
|
||||||
|
uint64_t copy_point;
|
||||||
if (wlr_ext_image_copy_capture_frame_v1_copy_buffer(frame,
|
if (wlr_ext_image_copy_capture_frame_v1_copy_buffer(frame,
|
||||||
event->buffer, source->output.renderer)) {
|
event->buffer, source->output.renderer,
|
||||||
wlr_ext_image_copy_capture_frame_v1_ready(frame,
|
event->wait_timeline, event->wait_point, ©_timeline, ©_point)) {
|
||||||
source->output.transform, &event->when);
|
if (copy_timeline != NULL) {
|
||||||
|
if (event->release_merger != NULL) {
|
||||||
|
wlr_drm_syncobj_merger_add(event->release_merger, copy_timeline, copy_point,
|
||||||
|
source->output.event_loop);
|
||||||
|
}
|
||||||
|
wlr_ext_image_copy_capture_frame_v1_ready_deferred(frame,
|
||||||
|
source->output.transform, &event->when, copy_timeline, copy_point);
|
||||||
|
wlr_drm_syncobj_timeline_unref(copy_timeline);
|
||||||
|
} else {
|
||||||
|
wlr_ext_image_copy_capture_frame_v1_ready(frame,
|
||||||
|
source->output.transform, &event->when);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,7 +180,14 @@ static const struct wlr_ext_image_capture_source_v1_interface source_impl = {
|
||||||
.copy_frame = source_copy_frame,
|
.copy_frame = source_copy_frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct wlr_backend_impl backend_impl = {0};
|
static int source_backend_get_drm_fd(struct wlr_backend *backend) {
|
||||||
|
struct scene_node_source *source = wl_container_of(backend, source, backend);
|
||||||
|
return wlr_renderer_get_drm_fd(source->output.renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wlr_backend_impl backend_impl = {
|
||||||
|
.get_drm_fd = source_backend_get_drm_fd
|
||||||
|
};
|
||||||
|
|
||||||
static void source_update_buffer_constraints(struct scene_node_source *source,
|
static void source_update_buffer_constraints(struct scene_node_source *source,
|
||||||
const struct wlr_output_state *state) {
|
const struct wlr_output_state *state) {
|
||||||
|
|
@ -180,6 +205,8 @@ static bool output_test(struct wlr_output *output, const struct wlr_output_state
|
||||||
uint32_t supported =
|
uint32_t supported =
|
||||||
WLR_OUTPUT_STATE_BACKEND_OPTIONAL |
|
WLR_OUTPUT_STATE_BACKEND_OPTIONAL |
|
||||||
WLR_OUTPUT_STATE_BUFFER |
|
WLR_OUTPUT_STATE_BUFFER |
|
||||||
|
WLR_OUTPUT_STATE_WAIT_TIMELINE |
|
||||||
|
WLR_OUTPUT_STATE_SIGNAL_TIMELINE |
|
||||||
WLR_OUTPUT_STATE_ENABLED |
|
WLR_OUTPUT_STATE_ENABLED |
|
||||||
WLR_OUTPUT_STATE_MODE;
|
WLR_OUTPUT_STATE_MODE;
|
||||||
if ((state->committed & ~supported) != 0) {
|
if ((state->committed & ~supported) != 0) {
|
||||||
|
|
@ -242,7 +269,16 @@ static bool output_commit(struct wlr_output *output, const struct wlr_output_sta
|
||||||
.buffer = buffer,
|
.buffer = buffer,
|
||||||
.when = now,
|
.when = now,
|
||||||
};
|
};
|
||||||
|
if (state->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) {
|
||||||
|
frame_event.wait_timeline = state->wait_timeline;
|
||||||
|
frame_event.wait_point = state->wait_point;
|
||||||
|
}
|
||||||
|
if (state->committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE) {
|
||||||
|
frame_event.release_merger = wlr_drm_syncobj_merger_create(
|
||||||
|
state->signal_timeline, state->signal_point);
|
||||||
|
}
|
||||||
wl_signal_emit_mutable(&source->base.events.frame, &frame_event.base);
|
wl_signal_emit_mutable(&source->base.events.frame, &frame_event.base);
|
||||||
|
wlr_drm_syncobj_merger_unref(frame_event.release_merger);
|
||||||
|
|
||||||
pixman_region32_fini(&full_damage);
|
pixman_region32_fini(&full_damage);
|
||||||
|
|
||||||
|
|
@ -311,6 +347,7 @@ struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_create_w
|
||||||
|
|
||||||
wlr_backend_init(&source->backend, &backend_impl);
|
wlr_backend_init(&source->backend, &backend_impl);
|
||||||
source->backend.buffer_caps = WLR_BUFFER_CAP_DMABUF | WLR_BUFFER_CAP_SHM;
|
source->backend.buffer_caps = WLR_BUFFER_CAP_DMABUF | WLR_BUFFER_CAP_SHM;
|
||||||
|
source->backend.features.timeline = true;
|
||||||
|
|
||||||
wlr_output_init(&source->output, &source->backend, &output_impl, event_loop, NULL);
|
wlr_output_init(&source->output, &source->backend, &output_impl, event_loop, NULL);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,9 @@ static void frame_destroy(struct wlr_ext_image_copy_capture_frame_v1 *frame) {
|
||||||
if (frame->session->frame == frame) {
|
if (frame->session->frame == frame) {
|
||||||
frame->session->frame = NULL;
|
frame->session->frame = NULL;
|
||||||
}
|
}
|
||||||
|
if (frame->copy_waiter_initialized) {
|
||||||
|
wlr_drm_syncobj_timeline_waiter_finish(&frame->copy_waiter);
|
||||||
|
}
|
||||||
free(frame);
|
free(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,16 +108,21 @@ void wlr_ext_image_copy_capture_frame_v1_ready(struct wlr_ext_image_copy_capture
|
||||||
frame_destroy(frame);
|
frame_destroy(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool copy_dmabuf(struct wlr_buffer *dst,
|
static bool copy_dmabuf(struct wlr_buffer *dst, struct wlr_buffer *src,
|
||||||
struct wlr_buffer *src, struct wlr_renderer *renderer,
|
struct wlr_renderer *renderer, const pixman_region32_t *clip,
|
||||||
const pixman_region32_t *clip) {
|
struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point,
|
||||||
|
struct wlr_drm_syncobj_timeline *signal_timeline, uint64_t signal_point) {
|
||||||
struct wlr_texture *texture = wlr_texture_from_buffer(renderer, src);
|
struct wlr_texture *texture = wlr_texture_from_buffer(renderer, src);
|
||||||
if (texture == NULL) {
|
if (texture == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, dst, NULL);
|
struct wlr_buffer_pass_options options = {
|
||||||
|
.signal_timeline = signal_timeline,
|
||||||
|
.signal_point = signal_point,
|
||||||
|
};
|
||||||
|
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, dst, &options);
|
||||||
if (!pass) {
|
if (!pass) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -123,6 +131,8 @@ static bool copy_dmabuf(struct wlr_buffer *dst,
|
||||||
.texture = texture,
|
.texture = texture,
|
||||||
.clip = clip,
|
.clip = clip,
|
||||||
.blend_mode = WLR_RENDER_BLEND_MODE_NONE,
|
.blend_mode = WLR_RENDER_BLEND_MODE_NONE,
|
||||||
|
.wait_timeline = wait_timeline,
|
||||||
|
.wait_point = wait_point,
|
||||||
});
|
});
|
||||||
|
|
||||||
ok = wlr_render_pass_submit(pass);
|
ok = wlr_render_pass_submit(pass);
|
||||||
|
|
@ -133,7 +143,8 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool copy_shm(void *data, uint32_t format, size_t stride,
|
static bool copy_shm(void *data, uint32_t format, size_t stride,
|
||||||
struct wlr_buffer *src, struct wlr_renderer *renderer) {
|
struct wlr_buffer *src, struct wlr_renderer *renderer,
|
||||||
|
struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point) {
|
||||||
// TODO: bypass renderer if source buffer supports data ptr access
|
// TODO: bypass renderer if source buffer supports data ptr access
|
||||||
struct wlr_texture *texture = wlr_texture_from_buffer(renderer, src);
|
struct wlr_texture *texture = wlr_texture_from_buffer(renderer, src);
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
|
|
@ -145,6 +156,8 @@ static bool copy_shm(void *data, uint32_t format, size_t stride,
|
||||||
.data = data,
|
.data = data,
|
||||||
.format = format,
|
.format = format,
|
||||||
.stride = stride,
|
.stride = stride,
|
||||||
|
.wait_timeline = wait_timeline,
|
||||||
|
.wait_point = wait_point,
|
||||||
});
|
});
|
||||||
|
|
||||||
wlr_texture_destroy(texture);
|
wlr_texture_destroy(texture);
|
||||||
|
|
@ -153,8 +166,16 @@ static bool copy_shm(void *data, uint32_t format, size_t stride,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_ext_image_copy_capture_frame_v1_copy_buffer(struct wlr_ext_image_copy_capture_frame_v1 *frame,
|
bool wlr_ext_image_copy_capture_frame_v1_copy_buffer(struct wlr_ext_image_copy_capture_frame_v1 *frame,
|
||||||
struct wlr_buffer *src, struct wlr_renderer *renderer) {
|
struct wlr_buffer *src, struct wlr_renderer *renderer,
|
||||||
|
struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point,
|
||||||
|
struct wlr_drm_syncobj_timeline **out_copy_timeline, uint64_t *out_copy_point) {
|
||||||
struct wlr_buffer *dst = frame->buffer;
|
struct wlr_buffer *dst = frame->buffer;
|
||||||
|
if (out_copy_timeline) {
|
||||||
|
*out_copy_timeline = NULL;
|
||||||
|
}
|
||||||
|
if (out_copy_point) {
|
||||||
|
*out_copy_point = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (src->width != dst->width || src->height != dst->height) {
|
if (src->width != dst->width || src->height != dst->height) {
|
||||||
wlr_ext_image_copy_capture_frame_v1_fail(frame,
|
wlr_ext_image_copy_capture_frame_v1_fail(frame,
|
||||||
|
|
@ -162,6 +183,20 @@ bool wlr_ext_image_copy_capture_frame_v1_copy_buffer(struct wlr_ext_image_copy_c
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wlr_drm_syncobj_timeline *copy_timeline = frame->session->copy_timeline;
|
||||||
|
if (copy_timeline == NULL && renderer->features.timeline) {
|
||||||
|
int drm_fd = wlr_renderer_get_drm_fd(renderer);
|
||||||
|
copy_timeline = wlr_drm_syncobj_timeline_create(drm_fd);
|
||||||
|
if (copy_timeline == NULL) {
|
||||||
|
wlr_ext_image_copy_capture_frame_v1_fail(frame,
|
||||||
|
EXT_IMAGE_COPY_CAPTURE_FRAME_V1_FAILURE_REASON_UNKNOWN);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
frame->session->copy_timeline = copy_timeline;
|
||||||
|
}
|
||||||
|
frame->session->copy_point++;
|
||||||
|
uint64_t copy_point = frame->session->copy_point;
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
enum ext_image_copy_capture_frame_v1_failure_reason failure_reason =
|
enum ext_image_copy_capture_frame_v1_failure_reason failure_reason =
|
||||||
EXT_IMAGE_COPY_CAPTURE_FRAME_V1_FAILURE_REASON_UNKNOWN;
|
EXT_IMAGE_COPY_CAPTURE_FRAME_V1_FAILURE_REASON_UNKNOWN;
|
||||||
|
|
@ -174,7 +209,18 @@ bool wlr_ext_image_copy_capture_frame_v1_copy_buffer(struct wlr_ext_image_copy_c
|
||||||
ok = false;
|
ok = false;
|
||||||
failure_reason = EXT_IMAGE_COPY_CAPTURE_FRAME_V1_FAILURE_REASON_BUFFER_CONSTRAINTS;
|
failure_reason = EXT_IMAGE_COPY_CAPTURE_FRAME_V1_FAILURE_REASON_BUFFER_CONSTRAINTS;
|
||||||
} else {
|
} else {
|
||||||
ok = copy_dmabuf(dst, src, renderer, &frame->buffer_damage);
|
if (out_copy_timeline == NULL) {
|
||||||
|
copy_timeline = NULL;
|
||||||
|
copy_point = 0;
|
||||||
|
}
|
||||||
|
ok = copy_dmabuf(dst, src, renderer, &frame->buffer_damage,
|
||||||
|
wait_timeline, wait_point, copy_timeline, copy_point);
|
||||||
|
if (ok && copy_timeline != NULL) {
|
||||||
|
*out_copy_timeline = wlr_drm_syncobj_timeline_ref(frame->session->copy_timeline);
|
||||||
|
}
|
||||||
|
if (ok && out_copy_point != NULL) {
|
||||||
|
*out_copy_point = copy_point;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (wlr_buffer_begin_data_ptr_access(dst,
|
} else if (wlr_buffer_begin_data_ptr_access(dst,
|
||||||
WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride)) {
|
WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride)) {
|
||||||
|
|
@ -182,7 +228,7 @@ bool wlr_ext_image_copy_capture_frame_v1_copy_buffer(struct wlr_ext_image_copy_c
|
||||||
ok = false;
|
ok = false;
|
||||||
failure_reason = EXT_IMAGE_COPY_CAPTURE_FRAME_V1_FAILURE_REASON_BUFFER_CONSTRAINTS;
|
failure_reason = EXT_IMAGE_COPY_CAPTURE_FRAME_V1_FAILURE_REASON_BUFFER_CONSTRAINTS;
|
||||||
} else {
|
} else {
|
||||||
ok = copy_shm(data, format, stride, src, renderer);
|
ok = copy_shm(data, format, stride, src, renderer, wait_timeline, wait_point);
|
||||||
}
|
}
|
||||||
wlr_buffer_end_data_ptr_access(dst);
|
wlr_buffer_end_data_ptr_access(dst);
|
||||||
}
|
}
|
||||||
|
|
@ -200,6 +246,37 @@ void wlr_ext_image_copy_capture_frame_v1_fail(struct wlr_ext_image_copy_capture_
|
||||||
frame_destroy(frame);
|
frame_destroy(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void frame_handle_copy_done(struct wlr_drm_syncobj_timeline_waiter *waiter) {
|
||||||
|
struct wlr_ext_image_copy_capture_frame_v1 *frame = wl_container_of(waiter, frame, copy_waiter);
|
||||||
|
wlr_ext_image_copy_capture_frame_v1_ready(frame, frame->pending_transform,
|
||||||
|
&frame->pending_presentation_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wlr_ext_image_copy_capture_frame_v1_ready_deferred(
|
||||||
|
struct wlr_ext_image_copy_capture_frame_v1 *frame,
|
||||||
|
enum wl_output_transform transform, const struct timespec *presentation_time,
|
||||||
|
struct wlr_drm_syncobj_timeline *timeline, uint64_t point) {
|
||||||
|
assert(!frame->copy_waiter_initialized);
|
||||||
|
|
||||||
|
frame->pending_transform = transform;
|
||||||
|
frame->pending_presentation_time = *presentation_time;
|
||||||
|
struct wl_display *display = wl_client_get_display(frame->resource->client);
|
||||||
|
struct wl_event_loop *event_loop = wl_display_get_event_loop(display);
|
||||||
|
bool ok = wlr_drm_syncobj_timeline_waiter_init(&frame->copy_waiter, timeline, point,
|
||||||
|
0, event_loop, frame_handle_copy_done);
|
||||||
|
frame->copy_waiter_initialized = ok;
|
||||||
|
if (ok) {
|
||||||
|
if (frame->session->frame == frame) {
|
||||||
|
frame->session->frame = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wlr_ext_image_copy_capture_frame_v1_fail(frame,
|
||||||
|
EXT_IMAGE_COPY_CAPTURE_FRAME_V1_FAILURE_REASON_UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
static void frame_handle_destroy(struct wl_client *client,
|
static void frame_handle_destroy(struct wl_client *client,
|
||||||
struct wl_resource *frame_resource) {
|
struct wl_resource *frame_resource) {
|
||||||
wl_resource_destroy(frame_resource);
|
wl_resource_destroy(frame_resource);
|
||||||
|
|
@ -397,6 +474,7 @@ static void session_destroy(struct wlr_ext_image_copy_capture_session_v1 *sessio
|
||||||
wl_resource_set_user_data(session->resource, NULL);
|
wl_resource_set_user_data(session->resource, NULL);
|
||||||
|
|
||||||
pixman_region32_fini(&session->damage);
|
pixman_region32_fini(&session->damage);
|
||||||
|
wlr_drm_syncobj_timeline_unref(session->copy_timeline);
|
||||||
wl_list_remove(&session->source_destroy.link);
|
wl_list_remove(&session->source_destroy.link);
|
||||||
wl_list_remove(&session->source_constraints_update.link);
|
wl_list_remove(&session->source_constraints_update.link);
|
||||||
wl_list_remove(&session->source_frame.link);
|
wl_list_remove(&session->source_frame.link);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue