mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-10-29 05:40:12 -04:00 
			
		
		
		
	Update example and protocol
This commit is contained in:
		
							parent
							
								
									21928cbe61
								
							
						
					
					
						commit
						9eddcbc376
					
				
					 2 changed files with 100 additions and 104 deletions
				
			
		|  | @ -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, | ||||
| }; | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <protocol name="wlr_export_dmabuf_unstable_v1"> | ||||
| 
 | ||||
|   <copyright> | ||||
|     Copyright © 2018 Rostislav Pehlivanov | ||||
| 
 | ||||
|  | @ -25,29 +24,56 @@ | |||
|   </copyright> | ||||
| 
 | ||||
|   <description summary="a protocol for low overhead screen content capturing"> | ||||
|     An interface to capture surfaces in an efficient way. | ||||
|     Overall usage: | ||||
|     An interface to capture surfaces in an efficient way by exporting DMA-BUFs. | ||||
| 
 | ||||
|     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.) | ||||
|     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. | ||||
|   </description> | ||||
| 
 | ||||
|   <interface name="zwlr_export_dmabuf_frame_v1" version="1"> | ||||
|     <description summary="a frame ready for readout"> | ||||
|       This object represents a frame which is ready to have its resources | ||||
|       fetched and used. | ||||
|   <interface name="zwlr_export_dmabuf_manager_v1" version="1"> | ||||
|     <description summary="manager to inform clients and begin capturing"> | ||||
|       This object is a manager with which to start capturing from sources. | ||||
|     </description> | ||||
| 
 | ||||
|     <request name="capture_output"> | ||||
|       <description summary="capture a frame from an output"> | ||||
|         Capture the next frame of a an entire output. | ||||
|       </description> | ||||
|       <arg name="frame" type="new_id" interface="zwlr_export_dmabuf_frame_v1"/> | ||||
|       <arg name="overlay_cursor" type="int" | ||||
|            summary="include custom client hardware cursor on top of the frame"/> | ||||
|       <arg name="output" type="object" interface="wl_output"/> | ||||
|     </request> | ||||
| 
 | ||||
|     <request name="destroy" type="destructor"> | ||||
|       <description summary="destroy the manager"> | ||||
|         All objects created by the manager will still remain valid, until their | ||||
|         appropriate destroy request has been called. | ||||
|       </description> | ||||
|     </request> | ||||
|   </interface> | ||||
| 
 | ||||
|   <interface name="zwlr_export_dmabuf_frame_v1" version="1"> | ||||
|     <description summary="a DMA-BUF frame"> | ||||
|       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. | ||||
| 
 | ||||
|       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. | ||||
|       All frames are read-only and may not be written into or altered. | ||||
|     </description> | ||||
| 
 | ||||
|  | @ -55,25 +81,23 @@ | |||
|       <description summary="frame flags"> | ||||
|         Special flags that should be respected by the client. | ||||
|       </description> | ||||
|       <entry name="transient" value="0x1" since="1" | ||||
|       <entry name="transient" value="0x1" | ||||
|              summary="clients should copy frame before processing"/> | ||||
|     </enum> | ||||
| 
 | ||||
|     <event name="frame"> | ||||
|       <description summary="main callback"> | ||||
|         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. | ||||
|       <description summary="a frame description"> | ||||
|         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. | ||||
| 
 | ||||
|         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. | ||||
|         This event is followed by a number of "object" as specified by the | ||||
|         "num_objects" argument. | ||||
|       </description> | ||||
|       <arg name="width" type="uint" | ||||
|            summary="frame width, scaling factor included"/> | ||||
|            summary="frame width in pixels"/> | ||||
|       <arg name="height" type="uint" | ||||
|            summary="frame height, scaling factor included"/> | ||||
|            summary="frame height in pixels"/> | ||||
|       <arg name="offset_x" type="uint" | ||||
|            summary="crop offset for the x axis"/> | ||||
|       <arg name="offset_y" type="uint" | ||||
|  | @ -91,13 +115,15 @@ | |||
|            summary="drm format modifier, low"/> | ||||
|       <arg name="num_objects" type="uint" | ||||
|            summary="indicates how many objects (FDs) the frame has (max 4)"/> | ||||
|       <arg name="num_planes" type="uint" | ||||
|            summary="indicates how many planes the frame has (max 4)"/> | ||||
|     </event> | ||||
| 
 | ||||
|     <event name="object"> | ||||
|       <description summary="object receiving callback"> | ||||
|         Callback which serves to supply the client with the file descriptors | ||||
|       <description summary="an object description"> | ||||
|         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. | ||||
|       </description> | ||||
|       <arg name="index" type="uint" | ||||
|            summary="index of the current object"/> | ||||
|  | @ -105,31 +131,28 @@ | |||
|            summary="fd of the current object"/> | ||||
|       <arg name="size" type="uint" | ||||
|            summary="size in bytes for the current object"/> | ||||
|     </event> | ||||
|     <event name="plane"> | ||||
|       <description summary="plane info receiving callback"> | ||||
|         Callback which supplies the client with plane information for each | ||||
|         plane. | ||||
|       </description> | ||||
|       <arg name="index" type="uint" | ||||
|            summary="index of the current plane"/> | ||||
|       <arg name="object_index" type="uint" | ||||
|            summary="index of the object the plane applies to"/> | ||||
|       <arg name="offset" type="uint" | ||||
|            summary="starting point for the data in the object's fd"/> | ||||
|       <arg name="stride" type="uint" | ||||
|            summary="line size in bytes"/> | ||||
|       <arg name="plane_index" type="uint" | ||||
|            summary="index of the the plane the data in the object applies to"/> | ||||
|     </event> | ||||
| 
 | ||||
|     <event name="ready"> | ||||
|       <description summary="indicates frame is available for reading"> | ||||
|         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. | ||||
|       </description> | ||||
|       <arg name="tv_sec_hi" type="uint" | ||||
|            summary="high 32 bits of the seconds part of the timestamp"/> | ||||
|  | @ -143,22 +166,25 @@ | |||
|       <description summary="cancel reason"> | ||||
|         Indicates reason for cancelling the frame. | ||||
|       </description> | ||||
|       <entry name="temporary" value="0" since="1" | ||||
|       <entry name="temporary" value="0" | ||||
|              summary="temporary error, source will produce more frames"/> | ||||
|       <entry name="pernament" value="1" since="1" | ||||
|       <entry name="permanent" value="1" | ||||
|              summary="fatal error, source will not produce frames"/> | ||||
|       <entry name="resizing" value="2" since="1" | ||||
|              summary="temporary error, source will produce frames"/> | ||||
|       <entry name="resizing" value="2" | ||||
|              summary="temporary error, source will produce more frames"/> | ||||
|     </enum> | ||||
| 
 | ||||
|     <event name="cancel"> | ||||
|       <description summary="indicates the frame is no longer valid"> | ||||
|         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. | ||||
|       </description> | ||||
|       <arg name="reason" type="uint" enum="cancel_reason" | ||||
|            summary="indicates a reason for cancelling this frame capture"/> | ||||
|  | @ -166,35 +192,11 @@ | |||
| 
 | ||||
|     <request name="destroy" type="destructor"> | ||||
|       <description summary="delete this object, used or not"> | ||||
|         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. | ||||
|       </description> | ||||
|     </request> | ||||
|   </interface> | ||||
|         Unreferences the frame. This request must be called as soon as its no | ||||
|         longer used. | ||||
| 
 | ||||
|   <interface name="zwlr_export_dmabuf_manager_v1" version="1"> | ||||
|     <description summary="manager to inform clients and begin capturing"> | ||||
|       This object is a manager with which to start capturing from sources. | ||||
|     </description> | ||||
| 
 | ||||
|     <request name="capture_output"> | ||||
|       <description summary="subscribe to start capturing"> | ||||
|         Request to start capturing from an entire wl_output. | ||||
|       </description> | ||||
|       <arg name="frame" type="new_id" | ||||
|            interface="zwlr_export_dmabuf_frame_v1"/> | ||||
|       <arg name="overlay_cursor" type="int" | ||||
|            summary="include custom client hardware cursor on top of the frame"/> | ||||
|       <arg name="output" type="object" interface="wl_output"/> | ||||
|     </request> | ||||
|     <request name="destroy" type="destructor"> | ||||
|       <description summary="destroy the manager"> | ||||
|         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. | ||||
|       </description> | ||||
|     </request> | ||||
|   </interface> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Rostislav Pehlivanov
						Rostislav Pehlivanov