From 9eddcbc376ff92a3a03002b910c31bf96bdba2da Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sun, 17 Jun 2018 14:06:52 +0100 Subject: [PATCH] Update example and protocol --- examples/dmabuf-capture.c | 28 ++-- protocol/wlr-export-dmabuf-unstable-v1.xml | 180 +++++++++++---------- 2 files changed, 102 insertions(+), 106 deletions(-) diff --git a/examples/dmabuf-capture.c b/examples/dmabuf-capture.c index cd8a9267..2f7db2f1 100644 --- a/examples/dmabuf-capture.c +++ b/examples/dmabuf-capture.c @@ -163,8 +163,7 @@ static void frame_free(void *opaque, uint8_t *data) { static void frame_start(void *data, struct zwlr_export_dmabuf_frame_v1 *frame, uint32_t width, uint32_t height, uint32_t offset_x, uint32_t offset_y, uint32_t buffer_flags, uint32_t flags, uint32_t format, - uint32_t mod_high, uint32_t mod_low, uint32_t num_objects, - uint32_t num_planes) { + uint32_t mod_high, uint32_t mod_low, uint32_t num_objects) { struct capture_context *ctx = data; int err = 0; @@ -180,7 +179,6 @@ static void frame_start(void *data, struct zwlr_export_dmabuf_frame_v1 *frame, desc->nb_layers = 1; desc->layers[0].format = format; - desc->layers[0].nb_planes = num_planes; /* Allocate a frame */ AVFrame *f = av_frame_alloc(); @@ -213,25 +211,18 @@ fail: } static void frame_object(void *data, struct zwlr_export_dmabuf_frame_v1 *frame, - uint32_t index, int32_t fd, uint32_t size) { + uint32_t index, int32_t fd, uint32_t size, uint32_t offset, + uint32_t stride, uint32_t plane_index) { struct capture_context *ctx = data; AVFrame *f = ctx->current_frame; AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)f->data[0]; desc->objects[index].fd = fd; desc->objects[index].size = size; -} - -static void frame_plane(void *data, struct zwlr_export_dmabuf_frame_v1 *frame, - uint32_t index, uint32_t object_index, - uint32_t offset, uint32_t stride) { - struct capture_context *ctx = data; - AVFrame *f = ctx->current_frame; - AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)f->data[0]; - desc->layers[0].planes[index].object_index = object_index; - desc->layers[0].planes[index].offset = offset; - desc->layers[0].planes[index].pitch = stride; + desc->layers[0].planes[plane_index].object_index = index; + desc->layers[0].planes[plane_index].offset = offset; + desc->layers[0].planes[plane_index].pitch = stride; } static const uint32_t pixfmt_to_drm_map[] = { @@ -311,14 +302,18 @@ static void frame_ready(void *data, struct zwlr_export_dmabuf_frame_v1 *frame, struct capture_context *ctx = data; AVFrame *f = ctx->current_frame; AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)f->data[0]; + enum AVPixelFormat pix_fmt = drm_fmt_to_pixfmt(desc->layers[0].format); int err = 0; /* Attach the hardware frame context to the frame */ - err = attach_drm_frames_ref(ctx, f, drm_fmt_to_pixfmt(desc->layers[0].format)); + err = attach_drm_frames_ref(ctx, f, pix_fmt); if (err) { goto end; } + /* TODO: support multiplane stuff */ + desc->layers[0].nb_planes = av_pix_fmt_count_planes(pix_fmt); + AVFrame *mapped_frame = av_frame_alloc(); if (!mapped_frame) { err = AVERROR(ENOMEM); @@ -431,7 +426,6 @@ static void frame_cancel(void *data, struct zwlr_export_dmabuf_frame_v1 *frame, static const struct zwlr_export_dmabuf_frame_v1_listener frame_listener = { .frame = frame_start, .object = frame_object, - .plane = frame_plane, .ready = frame_ready, .cancel = frame_cancel, }; diff --git a/protocol/wlr-export-dmabuf-unstable-v1.xml b/protocol/wlr-export-dmabuf-unstable-v1.xml index 760345a7..751f7efb 100644 --- a/protocol/wlr-export-dmabuf-unstable-v1.xml +++ b/protocol/wlr-export-dmabuf-unstable-v1.xml @@ -1,6 +1,5 @@ - Copyright © 2018 Rostislav Pehlivanov @@ -25,29 +24,56 @@ - An interface to capture surfaces in an efficient way. - Overall usage: - - 1.) client registers with zwlr_screencontent_manager_v1 - 2.) server sends client info about surfaces via "receive_surface_info" - 3.) client subscribes to capture a surface via the "capture" requests - 4.) server sends client events via the "zwlr_screencontent_frame" interface - 5.) client finishes and informs server via the "frame_destroy" event - 6.) client optionally resubscribes via repeating steps 3.) through 5.) + An interface to capture surfaces in an efficient way by exporting DMA-BUFs. + + Warning! The protocol described in this file is experimental and + backward incompatible changes may be made. Backward compatible changes + may be added together with the corresponding interface version bump. + Backward incompatible changes are done by bumping the version number in + the protocol and interface names and resetting the interface version. + Once the protocol is to be declared stable, the 'z' prefix and the + version number in the protocol and interface names are removed and the + interface version number is reset. + + + This object is a manager with which to start capturing from sources. + + + + + Capture the next frame of a an entire output. + + + + + + + + + All objects created by the manager will still remain valid, until their + appropriate destroy request has been called. + + + + - - This object represents a frame which is ready to have its resources - fetched and used. - - The receive callback shall be called first, followed by the "object" - callback once per dmabuf object or the "plane" callback, once per dmabuf - plane. The "ready" event is called last to indicate that all the data has - been made available for readout, as well as the time at which presentation - happened at. The ownership of the frame is passed to the client, who's - responsible for destroying it via the "destroy" event once finished and - by calling close() on the file descriptors received. + + This object represents a single DMA-BUF frame. + + If the capture is successful, the compositor will first send a "frame" + event, followed by one or several "object". When the frame is available + for readout, the "ready" event is sent. + + If the capture failed, the "cancel" event is sent. This can happen anytime + before the "ready" event. + + Once either a "ready" or a "cancel" event is received, the client should + destroy the frame. Once an "object" event is received, the client is + responsible for closing the associated file descriptor. + All frames are read-only and may not be written into or altered. @@ -55,25 +81,23 @@ Special flags that should be respected by the client. - - - Main callback supplying the client with information about the frame, - as well as an object to serve as context for destruction. Always called - first before any other events. - - The "transform" argument describes the orientation needed to be applied - to correctly orient the buffer. For example, a buffer rotated by 90 - degrees will have a value of "3" here, corresponding to the need to - apply a 270 degree transpose to correctly present the buffer. + + Main event supplying the client with information about the frame. If the + capture didn't fail, this event is always emitted first before any other + events. + + This event is followed by a number of "object" as specified by the + "num_objects" argument. + summary="frame width in pixels"/> + summary="frame height in pixels"/> - + - - Callback which serves to supply the client with the file descriptors + + Event which serves to supply the client with the file descriptors containing the data for each object. + + After receiving this event, the client must always close the file + descriptor as soon as they're done with it and even if the frame fails. @@ -105,31 +131,28 @@ summary="fd of the current object"/> - - - - Callback which supplies the client with plane information for each - plane. - - - + + - Called as soon as the frame is presented, indicating it is available - for reading. + This event is sent as soon as the frame is presented, indicating it is + available for reading. This event includes the time at which + presentation happened at. + The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples, each component being an unsigned 32-bit value. Whole seconds are in tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo, and the additional fractional part in tv_nsec as nanoseconds. Hence, - for valid timestamps tv_nsec must be in [0, 999999999]. - The seconds part may have an arbitrary offset at start. + for valid timestamps tv_nsec must be in [0, 999999999]. The seconds part + may have an arbitrary offset at start. + + After receiving this event, the client should destroy this object. @@ -143,22 +166,25 @@ Indicates reason for cancelling the frame. - - - + - If the frame is no longer valid after the "frame" event has been called, - this callback will be used to inform the client to scrap the frame. - Source is still valid for as long as the subscription function does not - return NULL. - This may get called if for instance the surface is in the process of - resizing. + If the capture failed or if the frame is no longer valid after the + "frame" event has been emitted, this event will be used to inform the + client to scrap the frame. + + If the failure is temporary, the client may capture again the same + source. If the failure is permanent, any further attempts to capture the + same source will fail again. + + After receiving this event, the client should destroy this object. @@ -166,35 +192,11 @@ - Unreferences the frame, allowing it to be reused. Must be called as soon - as its no longer used. - Can be called at any time by the client after the "frame" event, after - which the compositor will not call any other events unless the client - resubscribes to capture more. The client will still have to close any - FDs it has been given. - - - + Unreferences the frame. This request must be called as soon as its no + longer used. - - - This object is a manager with which to start capturing from sources. - - - - - Request to start capturing from an entire wl_output. - - - - - - - - All objects created by the manager will still remain valid, until their - appropriate destroy request has been called. + It can be called at any time by the client. The client will still have + to close any FDs it has been given.