mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	backend/drm: send output layer feedback events
This commit is contained in:
		
							parent
							
								
									e1335a792a
								
							
						
					
					
						commit
						22d9df2af4
					
				
					 4 changed files with 77 additions and 1 deletions
				
			
		| 
						 | 
					@ -349,6 +349,7 @@ static void layer_handle_addon_destroy(struct wlr_addon *addon) {
 | 
				
			||||||
	drm_fb_clear(&layer->pending_fb);
 | 
						drm_fb_clear(&layer->pending_fb);
 | 
				
			||||||
	drm_fb_clear(&layer->queued_fb);
 | 
						drm_fb_clear(&layer->queued_fb);
 | 
				
			||||||
	drm_fb_clear(&layer->current_fb);
 | 
						drm_fb_clear(&layer->current_fb);
 | 
				
			||||||
 | 
						free(layer->candidate_planes);
 | 
				
			||||||
	free(layer);
 | 
						free(layer);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -381,6 +382,8 @@ static struct wlr_drm_layer *get_or_create_layer(struct wlr_drm_backend *drm,
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						layer->wlr = wlr_layer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if HAVE_LIBLIFTOFF
 | 
					#if HAVE_LIBLIFTOFF
 | 
				
			||||||
	layer->liftoff = liftoff_layer_create(crtc->liftoff);
 | 
						layer->liftoff = liftoff_layer_create(crtc->liftoff);
 | 
				
			||||||
	if (layer->liftoff == NULL) {
 | 
						if (layer->liftoff == NULL) {
 | 
				
			||||||
| 
						 | 
					@ -391,6 +394,15 @@ static struct wlr_drm_layer *get_or_create_layer(struct wlr_drm_backend *drm,
 | 
				
			||||||
	abort(); // unreachable
 | 
						abort(); // unreachable
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						layer->candidate_planes = calloc(sizeof(bool), drm->num_planes);
 | 
				
			||||||
 | 
						if (layer->candidate_planes == NULL) {
 | 
				
			||||||
 | 
					#if HAVE_LIBLIFTOFF
 | 
				
			||||||
 | 
							liftoff_layer_destroy(layer->liftoff);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							free(layer);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_addon_init(&layer->addon, &wlr_layer->addons, drm, &layer_impl);
 | 
						wlr_addon_init(&layer->addon, &wlr_layer->addons, drm, &layer_impl);
 | 
				
			||||||
	wl_list_insert(&crtc->layers, &layer->link);
 | 
						wl_list_insert(&crtc->layers, &layer->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
#define _POSIX_C_SOURCE 200809L
 | 
					#define _POSIX_C_SOURCE 200809L
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <libliftoff.h>
 | 
					#include <libliftoff.h>
 | 
				
			||||||
 | 
					#include <sys/stat.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <wlr/util/log.h>
 | 
					#include <wlr/util/log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -214,6 +215,62 @@ static bool set_layer_props(struct wlr_drm_backend *drm,
 | 
				
			||||||
		liftoff_layer_set_property(layer->liftoff, "SRC_H", src_h) == 0;
 | 
							liftoff_layer_set_property(layer->liftoff, "SRC_H", src_h) == 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool devid_from_fd(int fd, dev_t *devid) {
 | 
				
			||||||
 | 
						struct stat stat;
 | 
				
			||||||
 | 
						if (fstat(fd, &stat) != 0) {
 | 
				
			||||||
 | 
							wlr_log_errno(WLR_ERROR, "fstat failed");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*devid = stat.st_rdev;
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void update_layer_feedback(struct wlr_drm_backend *drm,
 | 
				
			||||||
 | 
							struct wlr_drm_layer *layer) {
 | 
				
			||||||
 | 
						bool changed = false;
 | 
				
			||||||
 | 
						for (size_t i = 0; i < drm->num_planes; i++) {
 | 
				
			||||||
 | 
							struct wlr_drm_plane *plane = &drm->planes[i];
 | 
				
			||||||
 | 
							bool is_candidate = liftoff_layer_is_candidate_plane(layer->liftoff,
 | 
				
			||||||
 | 
								plane->liftoff);
 | 
				
			||||||
 | 
							if (layer->candidate_planes[i] != is_candidate) {
 | 
				
			||||||
 | 
								layer->candidate_planes[i] = is_candidate;
 | 
				
			||||||
 | 
								changed = true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!changed) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_t target_device;
 | 
				
			||||||
 | 
						if (!devid_from_fd(drm->fd, &target_device)) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_drm_format_set formats = {0};
 | 
				
			||||||
 | 
						for (size_t i = 0; i < drm->num_planes; i++) {
 | 
				
			||||||
 | 
							struct wlr_drm_plane *plane = &drm->planes[i];
 | 
				
			||||||
 | 
							if (!layer->candidate_planes[i]) {
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (size_t j = 0; j < plane->formats.len; j++) {
 | 
				
			||||||
 | 
								const struct wlr_drm_format *format = plane->formats.formats[j];
 | 
				
			||||||
 | 
								for (size_t k = 0; k < format->len; k++) {
 | 
				
			||||||
 | 
									wlr_drm_format_set_add(&formats, format->format,
 | 
				
			||||||
 | 
										format->modifiers[k]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_output_layer_feedback_event event = {
 | 
				
			||||||
 | 
							.target_device = target_device,
 | 
				
			||||||
 | 
							.formats = &formats,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						wl_signal_emit_mutable(&layer->wlr->events.feedback, &event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_drm_format_set_finish(&formats);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool crtc_commit(struct wlr_drm_connector *conn,
 | 
					static bool crtc_commit(struct wlr_drm_connector *conn,
 | 
				
			||||||
		const struct wlr_drm_connector_state *state, uint32_t flags,
 | 
							const struct wlr_drm_connector_state *state, uint32_t flags,
 | 
				
			||||||
		bool test_only) {
 | 
							bool test_only) {
 | 
				
			||||||
| 
						 | 
					@ -380,6 +437,9 @@ static bool crtc_commit(struct wlr_drm_connector *conn,
 | 
				
			||||||
			struct wlr_drm_layer *layer = get_drm_layer(drm, layer_state->layer);
 | 
								struct wlr_drm_layer *layer = get_drm_layer(drm, layer_state->layer);
 | 
				
			||||||
			layer_state->accepted =
 | 
								layer_state->accepted =
 | 
				
			||||||
				!liftoff_layer_needs_composition(layer->liftoff);
 | 
									!liftoff_layer_needs_composition(layer->liftoff);
 | 
				
			||||||
 | 
								if (!test_only && !layer_state->accepted) {
 | 
				
			||||||
 | 
									update_layer_feedback(drm, layer);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ hwdata = dependency(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libliftoff = dependency(
 | 
					libliftoff = dependency(
 | 
				
			||||||
	'libliftoff',
 | 
						'libliftoff',
 | 
				
			||||||
	version: '>=0.2.0',
 | 
						version: '>=0.4.0',
 | 
				
			||||||
	fallback: 'libliftoff',
 | 
						fallback: 'libliftoff',
 | 
				
			||||||
	required: false,
 | 
						required: false,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,7 @@ struct wlr_drm_plane {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_drm_layer {
 | 
					struct wlr_drm_layer {
 | 
				
			||||||
 | 
						struct wlr_output_layer *wlr;
 | 
				
			||||||
	struct liftoff_layer *liftoff;
 | 
						struct liftoff_layer *liftoff;
 | 
				
			||||||
	struct wlr_addon addon; // wlr_output_layer.addons
 | 
						struct wlr_addon addon; // wlr_output_layer.addons
 | 
				
			||||||
	struct wl_list link; // wlr_drm_crtc.layers
 | 
						struct wl_list link; // wlr_drm_crtc.layers
 | 
				
			||||||
| 
						 | 
					@ -50,6 +51,9 @@ struct wlr_drm_layer {
 | 
				
			||||||
	struct wlr_drm_fb *current_fb;
 | 
						struct wlr_drm_fb *current_fb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int pending_width, pending_height;
 | 
						int pending_width, pending_height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// One entry per wlr_drm_backend.planes
 | 
				
			||||||
 | 
						bool *candidate_planes;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_drm_crtc {
 | 
					struct wlr_drm_crtc {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue