|  |  | @ -374,9 +374,13 @@ struct match_state { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	bool exit_early; |  |  |  | 	bool exit_early; | 
			
		
	
		
		
			
				
					
					|  |  |  | }; |  |  |  | }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #define UNMATCHED (uint32_t)-1 |  |  |  | enum { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	UNMATCHED = (uint32_t)-1, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	SKIP = (uint32_t)-2, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /*
 |  |  |  | /*
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * skips: The number of SKIP elements encountered so far. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * score: The number of resources we've matched so far. |  |  |  |  * score: The number of resources we've matched so far. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * replaced: The number of changes from the original solution. |  |  |  |  * replaced: The number of changes from the original solution. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * i: The index of the current element. |  |  |  |  * i: The index of the current element. | 
			
		
	
	
		
		
			
				
					|  |  | @ -385,7 +389,7 @@ struct match_state { | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  * Returns whether we've set a new best element with this solution. |  |  |  |  * Returns whether we've set a new best element with this solution. | 
			
		
	
		
		
			
				
					
					|  |  |  |  */ |  |  |  |  */ | 
			
		
	
		
		
			
				
					
					|  |  |  | static bool match_obj_(struct match_state *st, size_t score, size_t replaced, size_t i) { |  |  |  | static bool match_obj_(struct match_state *st, size_t skips, size_t score, size_t replaced, size_t i) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	// Finished
 |  |  |  | 	// Finished
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (i >= st->num_res) { |  |  |  | 	if (i >= st->num_res) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (score > st->score || (score == st->score && replaced < st->replaced)) { |  |  |  | 		if (score > st->score || (score == st->score && replaced < st->replaced)) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -396,6 +400,9 @@ static bool match_obj_(struct match_state *st, size_t score, size_t replaced, si | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (st->score == st->num_objs && st->replaced == 0) { |  |  |  | 			if (st->score == st->num_objs && st->replaced == 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 				st->exit_early = true; |  |  |  | 				st->exit_early = true; | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			st->exit_early = (st->score == st->num_res - skips | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 					|| st->score == st->num_objs) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 					&& st->replaced == 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			return true; |  |  |  | 			return true; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} else { |  |  |  | 		} else { | 
			
		
	
	
		
		
			
				
					|  |  | @ -403,6 +410,11 @@ static bool match_obj_(struct match_state *st, size_t score, size_t replaced, si | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (st->orig[i] == SKIP) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		st->res[i] = SKIP; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return match_obj_(st, skips + 1, score, replaced, i + 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/*
 |  |  |  | 	/*
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Attempt to use the current solution first, to try and avoid |  |  |  | 	 * Attempt to use the current solution first, to try and avoid | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * recalculating everything |  |  |  | 	 * recalculating everything | 
			
		
	
	
		
		
			
				
					|  |  | @ -410,7 +422,7 @@ static bool match_obj_(struct match_state *st, size_t score, size_t replaced, si | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (st->orig[i] != UNMATCHED && !is_taken(i, st->res, st->orig[i])) { |  |  |  | 	if (st->orig[i] != UNMATCHED && !is_taken(i, st->res, st->orig[i])) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		st->res[i] = st->orig[i]; |  |  |  | 		st->res[i] = st->orig[i]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (match_obj_(st, score + 1, replaced, i + 1)) { |  |  |  | 		if (match_obj_(st, skips, score + 1, replaced, i + 1)) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			return true; |  |  |  | 			return true; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
	
		
		
			
				
					|  |  | @ -436,7 +448,7 @@ static bool match_obj_(struct match_state *st, size_t score, size_t replaced, si | 
			
		
	
		
		
			
				
					
					|  |  |  | 			continue; |  |  |  | 			continue; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (match_obj_(st, score + 1, replaced, i + 1)) { |  |  |  | 		if (match_obj_(st, skips, score + 1, replaced, i + 1)) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			is_best = true; |  |  |  | 			is_best = true; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -451,7 +463,7 @@ static bool match_obj_(struct match_state *st, size_t score, size_t replaced, si | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	// Maybe this resource can't be matched
 |  |  |  | 	// Maybe this resource can't be matched
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	st->res[i] = UNMATCHED; |  |  |  | 	st->res[i] = UNMATCHED; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return match_obj_(st, score, replaced, i + 1); |  |  |  | 	return match_obj_(st, skips, score, replaced, i + 1); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /*
 |  |  |  | /*
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -464,6 +476,7 @@ static bool match_obj_(struct match_state *st, size_t score, size_t replaced, si | 
			
		
	
		
		
			
				
					
					|  |  |  |  * res contains an index of which objs it is matched with or UNMATCHED. |  |  |  |  * res contains an index of which objs it is matched with or UNMATCHED. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  * This solution is left in out. |  |  |  |  * This solution is left in out. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * Returns the total number of matched solutions. | 
			
		
	
		
		
			
				
					
					|  |  |  |  */ |  |  |  |  */ | 
			
		
	
		
		
			
				
					
					|  |  |  | static size_t match_obj(size_t num_objs, const uint32_t objs[static restrict num_objs], |  |  |  | static size_t match_obj(size_t num_objs, const uint32_t objs[static restrict num_objs], | 
			
		
	
		
		
			
				
					
					|  |  |  | 		size_t num_res, const uint32_t res[static restrict num_res], |  |  |  | 		size_t num_res, const uint32_t res[static restrict num_res], | 
			
		
	
	
		
		
			
				
					|  |  | @ -482,104 +495,140 @@ static size_t match_obj(size_t num_objs, const uint32_t objs[static restrict num | 
			
		
	
		
		
			
				
					
					|  |  |  | 		.exit_early = false, |  |  |  | 		.exit_early = false, | 
			
		
	
		
		
			
				
					
					|  |  |  | 	}; |  |  |  | 	}; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	match_obj_(&st, 0, 0, 0); |  |  |  | 	match_obj_(&st, 0, 0, 0, 0); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	return st.score; |  |  |  | 	return st.score; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static bool wlr_drm_output_set_mode(struct wlr_output_state *output, |  |  |  | static void realloc_planes(struct wlr_backend_state *drm, const uint32_t *crtc_in) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		struct wlr_output_mode *mode) { |  |  |  | 	for (int i = 0; i < 3; ++i) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	struct wlr_backend_state *drm = |  |  |  | 		if (drm->num_type_planes[i] == 0) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		wl_container_of(output->renderer, drm, renderer); |  |  |  | 			continue; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", output->base->name, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			mode->width, mode->height, mode->refresh); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	drmModeConnector *conn = drmModeGetConnector(drm->fd, output->connector); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (!conn) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		wlr_log_errno(L_ERROR, "Failed to get DRM connector"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		goto error; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		wlr_log(L_ERROR, "%s is not connected", output->base->name); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		goto error; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 		uint32_t possible[drm->num_type_planes[i]]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		size_t index; |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		uint32_t crtc[drm->num_crtcs]; |  |  |  | 		uint32_t crtc[drm->num_crtcs]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		uint32_t possible_crtc[drm->outputs->length]; |  |  |  | 		uint32_t crtc_res[drm->num_crtcs]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		memset(possible_crtc, 0, sizeof(possible_crtc)); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		for (size_t i = 0; i < drm->num_crtcs; ++i) { |  |  |  | 		for (size_t j = 0; j < drm->num_type_planes[i]; ++j) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			crtc[i] = UNMATCHED; |  |  |  | 			possible[j] = drm->type_planes[i][j].possible_crtcs; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		for (size_t i = 0; i < drm->outputs->length; ++i) { |  |  |  | 		for (size_t j = 0; j < drm->num_crtcs; ++j) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			struct wlr_output_state *o = drm->outputs->items[i]; |  |  |  | 			if (crtc_in[j] == UNMATCHED) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			if (o == output) { |  |  |  | 				crtc[j] = SKIP; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				index = i; |  |  |  | 				continue; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (o->state != WLR_DRM_OUTPUT_CONNECTED) { |  |  |  | 			if (drm->crtcs[j].planes[j]) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				continue; |  |  |  | 				crtc[j] = drm->crtcs[j].planes[i] - drm->type_planes[i]; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				crtc[j] = UNMATCHED; | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		match_obj(drm->num_type_planes[i], possible, drm->num_crtcs, crtc, crtc_res); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			possible_crtc[i] = o->possible_crtc; |  |  |  | 		for (size_t j = 0; j < drm->num_crtcs; ++j) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			crtc[o->crtc_ - drm->crtcs] = i; |  |  |  | 			struct wlr_drm_crtc *c = &drm->crtcs[j]; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			c->planes[i] = &drm->type_planes[i][crtc_res[j]]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	}; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		for (int i = 0; i < conn->count_encoders; ++i) { |  |  |  | static void realloc_crtcs(struct wlr_backend_state *drm, struct wlr_output_state *output) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			drmModeEncoder *enc = drmModeGetEncoder(drm->fd, conn->encoders[i]); |  |  |  | 	bool handled[drm->outputs->length]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			if (!enc) { |  |  |  | 	uint32_t crtc[drm->num_crtcs]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				continue; |  |  |  | 	uint32_t crtc_res[drm->num_crtcs]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 	uint32_t possible_crtc[drm->outputs->length]; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			uint32_t res[drm->num_crtcs]; |  |  |  | 	for (size_t i = 0; i < drm->num_crtcs; ++i) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		crtc[i] = UNMATCHED; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			possible_crtc[index] = enc->possible_crtcs; |  |  |  | 	memset(possible_crtc, 0, sizeof(possible_crtc)); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			match_obj(drm->outputs->length, possible_crtc, drm->num_crtcs, crtc, res); |  |  |  | 	memset(handled, 0, sizeof(handled)); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			wlr_log(L_DEBUG, "-----"); |  |  |  | 	size_t index; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			for (size_t i = 0; i < drm->num_crtcs; ++i) { |  |  |  | 	for (size_t i = 0; i < drm->outputs->length; ++i) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				wlr_log(L_DEBUG, "%d", (int)res[i]); |  |  |  | 		struct wlr_output_state *o = drm->outputs->items[i]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 		if (o == output) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			wlr_log(L_DEBUG, "-----"); |  |  |  | 			index = i; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			bool handled[drm->outputs->length]; |  |  |  | 		if (o->state != WLR_DRM_OUTPUT_CONNECTED) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			memset(handled, 0, sizeof(handled)); |  |  |  | 			continue; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			for (size_t i = 0; i < drm->num_crtcs; ++i) { |  |  |  | 		possible_crtc[i] = o->possible_crtc; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				if (res[i] == UNMATCHED) { |  |  |  | 		crtc[o->crtc_ - drm->crtcs] = i; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 					continue; |  |  |  | 	} | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				} |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 				handled[res[i]] = true; |  |  |  | 	possible_crtc[index] = output->possible_crtc; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	match_obj(drm->outputs->length, possible_crtc, drm->num_crtcs, crtc, crtc_res); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 				if (res[i] != crtc[i]) { |  |  |  | 	realloc_planes(drm, crtc_res); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 					struct wlr_output_state *o = drm->outputs->items[res[i]]; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					o->crtc_ = &drm->crtcs[i]; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					o->crtc = o->crtc_->id; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			for (size_t i = 0; i < drm->num_crtcs; ++i) { |  |  |  | 	for (size_t i = 0; i < drm->num_crtcs; ++i) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				if (!handled[i]) { |  |  |  | 		if (crtc_res[i] == UNMATCHED) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 					wlr_drm_output_cleanup(drm->outputs->items[i], false); |  |  |  | 			continue; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				} |  |  |  | 		} | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (!output->crtc_) { |  |  |  | 		handled[crtc_res[i]] = true; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				wlr_log(L_ERROR, "Unable to match %s with a CRTC", output->base->name); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				goto error; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			output->possible_crtc = enc->possible_crtcs; |  |  |  | 		if (crtc_res[i] != crtc[i]) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			struct wlr_output_state *o = drm->outputs->items[crtc_res[i]]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			o->crtc_ = &drm->crtcs[i]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			o->crtc = o->crtc_->id; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 			drmModeFreeEncoder(enc); |  |  |  | 	for (size_t i = 0; i < drm->outputs->length; ++i) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			break; |  |  |  | 		if (!handled[i]) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			wlr_drm_output_cleanup(drm->outputs->items[i], false); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static bool wlr_drm_output_set_mode(struct wlr_output_state *output, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		struct wlr_output_mode *mode) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	struct wlr_backend_state *drm = wl_container_of(output->renderer, drm, renderer); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", output->base->name, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			mode->width, mode->height, mode->refresh); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	drmModeConnector *conn = drmModeGetConnector(drm->fd, output->connector); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (!conn) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		wlr_log_errno(L_ERROR, "Failed to get DRM connector"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		goto error_output; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		wlr_log(L_ERROR, "%s is not connected", output->base->name); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		goto error_output; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	drmModeEncoder *enc = NULL; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	for (int i = 0; !enc && i < conn->count_encoders; ++i) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		enc = drmModeGetEncoder(drm->fd, conn->encoders[i]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (!enc) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		wlr_log(L_ERROR, "Failed to get DRM encoder"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		goto error_conn; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	output->possible_crtc = enc->possible_crtcs; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	realloc_crtcs(drm, output); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	if (!output->crtc_) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		wlr_log(L_ERROR, "Unable to match %s with a CRTC", output->base->name); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		goto error_enc; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	struct wlr_drm_crtc *crtc = output->crtc_; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	wlr_log(L_DEBUG, "%s: crtc=%ju ovr=%jd pri=%jd cur=%jd", output->base->name, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		crtc - drm->crtcs, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		crtc->overlay ? crtc->overlay - drm->overlay_planes : -1, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		crtc->primary ? crtc->primary - drm->primary_planes : -1, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		crtc->cursor ? crtc->cursor - drm->cursor_planes : -1); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	output->state = WLR_DRM_OUTPUT_CONNECTED; |  |  |  | 	output->state = WLR_DRM_OUTPUT_CONNECTED; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	output->width = output->base->width = mode->width; |  |  |  | 	output->width = output->base->width = mode->width; | 
			
		
	
	
		
		
			
				
					|  |  | @ -589,15 +638,19 @@ static bool wlr_drm_output_set_mode(struct wlr_output_state *output, | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (!display_init_renderer(&drm->renderer, output)) { |  |  |  | 	if (!display_init_renderer(&drm->renderer, output)) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 		wlr_log(L_ERROR, "Failed to initalise renderer for %s", output->base->name); |  |  |  | 		wlr_log(L_ERROR, "Failed to initalise renderer for %s", output->base->name); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		goto error; |  |  |  | 		goto error_enc; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	drmModeFreeEncoder(enc); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	drmModeFreeConnector(conn); |  |  |  | 	drmModeFreeConnector(conn); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return true; |  |  |  | 	return true; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | error: |  |  |  | error_enc: | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	wlr_drm_output_cleanup(output, false); |  |  |  | 	drmModeFreeEncoder(enc); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | error_conn: | 
			
		
	
		
		
			
				
					
					|  |  |  | 	drmModeFreeConnector(conn); |  |  |  | 	drmModeFreeConnector(conn); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | error_output: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	wlr_drm_output_cleanup(output, false); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	return false; |  |  |  | 	return false; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | 
 |