mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-10-29 05:40:12 -04:00 
			
		
		
		
	Compare commits
	
		
			14 commits
		
	
	
		
			93b49f26e2
			...
			c7ae497eab
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | c7ae497eab | ||
|   | 879243e370 | ||
|   | 989cffe70d | ||
|   | 3e08e3be4a | ||
|   | 91f4890ec2 | ||
|   | 74ce6c22a5 | ||
|   | 0b58bddf13 | ||
|   | 3d36ab9211 | ||
|   | d786e07899 | ||
|   | 6d63871f05 | ||
|   | 19c5d22beb | ||
|   | 06275103f2 | ||
|   | 03e7966650 | ||
|   | 18c707d90a | 
					 18 changed files with 310 additions and 64 deletions
				
			
		|  | @ -41,9 +41,10 @@ tasks: | ||||||
|       cd wlroots/build-gcc/tinywl |       cd wlroots/build-gcc/tinywl | ||||||
|       sudo modprobe vkms |       sudo modprobe vkms | ||||||
|       udevadm settle |       udevadm settle | ||||||
|  |       card="/dev/dri/$(ls /sys/devices/faux/vkms/drm/ | grep ^card)" | ||||||
|       export WLR_BACKENDS=drm |       export WLR_BACKENDS=drm | ||||||
|       export WLR_RENDERER=pixman |       export WLR_RENDERER=pixman | ||||||
|       export WLR_DRM_DEVICES=/dev/dri/by-path/platform-vkms-card |       export WLR_DRM_DEVICES="$card" | ||||||
|       export UBSAN_OPTIONS=halt_on_error=1 |       export UBSAN_OPTIONS=halt_on_error=1 | ||||||
|       sudo chmod ugo+rw /dev/dri/by-path/platform-vkms-card |       sudo chmod ugo+rw "$card" | ||||||
|       sudo -E seatd-launch -- ./tinywl -s 'kill $PPID' || [ $? = 143 ] |       sudo -E seatd-launch -- ./tinywl -s 'kill $PPID' || [ $? = 143 ] | ||||||
|  |  | ||||||
|  | @ -519,8 +519,6 @@ ssize_t wlr_session_find_gpus(struct wlr_session *session, | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		bool is_boot_vga = false; |  | ||||||
| 
 |  | ||||||
| 		const char *path = udev_list_entry_get_name(entry); | 		const char *path = udev_list_entry_get_name(entry); | ||||||
| 		struct udev_device *dev = udev_device_new_from_syspath(session->udev, path); | 		struct udev_device *dev = udev_device_new_from_syspath(session->udev, path); | ||||||
| 		if (!dev) { | 		if (!dev) { | ||||||
|  | @ -536,14 +534,20 @@ ssize_t wlr_session_find_gpus(struct wlr_session *session, | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// This is owned by 'dev', so we don't need to free it
 | 		bool is_primary = false; | ||||||
| 		struct udev_device *pci = | 		const char *boot_display = udev_device_get_sysattr_value(dev, "boot_display"); | ||||||
| 			udev_device_get_parent_with_subsystem_devtype(dev, "pci", NULL); | 		if (boot_display && strcmp(boot_display, "1") == 0) { | ||||||
|  | 		    is_primary = true; | ||||||
|  | 		} else { | ||||||
|  | 			// This is owned by 'dev', so we don't need to free it
 | ||||||
|  | 			struct udev_device *pci = | ||||||
|  | 				udev_device_get_parent_with_subsystem_devtype(dev, "pci", NULL); | ||||||
| 
 | 
 | ||||||
| 		if (pci) { | 			if (pci) { | ||||||
| 			const char *id = udev_device_get_sysattr_value(pci, "boot_vga"); | 				const char *id = udev_device_get_sysattr_value(pci, "boot_vga"); | ||||||
| 			if (id && strcmp(id, "1") == 0) { | 				if (id && strcmp(id, "1") == 0) { | ||||||
| 				is_boot_vga = true; | 					is_primary = true; | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -557,7 +561,7 @@ ssize_t wlr_session_find_gpus(struct wlr_session *session, | ||||||
| 		udev_device_unref(dev); | 		udev_device_unref(dev); | ||||||
| 
 | 
 | ||||||
| 		ret[i] = wlr_dev; | 		ret[i] = wlr_dev; | ||||||
| 		if (is_boot_vga) { | 		if (is_primary) { | ||||||
| 			struct wlr_device *tmp = ret[0]; | 			struct wlr_device *tmp = ret[0]; | ||||||
| 			ret[0] = ret[i]; | 			ret[0] = ret[i]; | ||||||
| 			ret[i] = tmp; | 			ret[i] = tmp; | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ enum wlr_color_transform_type { | ||||||
| 	COLOR_TRANSFORM_INVERSE_EOTF, | 	COLOR_TRANSFORM_INVERSE_EOTF, | ||||||
| 	COLOR_TRANSFORM_LCMS2, | 	COLOR_TRANSFORM_LCMS2, | ||||||
| 	COLOR_TRANSFORM_LUT_3X1D, | 	COLOR_TRANSFORM_LUT_3X1D, | ||||||
|  | 	COLOR_TRANSFORM_PIPELINE, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct wlr_color_transform { | struct wlr_color_transform { | ||||||
|  | @ -39,6 +40,13 @@ struct wlr_color_transform_lut_3x1d { | ||||||
| 	size_t dim; | 	size_t dim; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct wlr_color_transform_pipeline { | ||||||
|  | 	struct wlr_color_transform base; | ||||||
|  | 
 | ||||||
|  | 	struct wlr_color_transform **transforms; | ||||||
|  | 	size_t len; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| void wlr_color_transform_init(struct wlr_color_transform *tr, | void wlr_color_transform_init(struct wlr_color_transform *tr, | ||||||
| 	enum wlr_color_transform_type type); | 	enum wlr_color_transform_type type); | ||||||
| 
 | 
 | ||||||
|  | @ -72,12 +80,6 @@ struct wlr_color_transform_inverse_eotf *wlr_color_transform_inverse_eotf_from_b | ||||||
| struct wlr_color_transform_lut_3x1d *color_transform_lut_3x1d_from_base( | struct wlr_color_transform_lut_3x1d *color_transform_lut_3x1d_from_base( | ||||||
| 	struct wlr_color_transform *tr); | 	struct wlr_color_transform *tr); | ||||||
| 
 | 
 | ||||||
| /**
 |  | ||||||
|  * Evaluate a 3x1D LUT color transform for a given RGB triplet. |  | ||||||
|  */ |  | ||||||
| void color_transform_lut_3x1d_eval(struct wlr_color_transform_lut_3x1d *tr, |  | ||||||
| 	float out[static 3], const float in[static 3]); |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * Obtain primaries values from a well-known primaries name. |  * Obtain primaries values from a well-known primaries name. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | @ -141,6 +141,13 @@ struct wlr_color_transform *wlr_color_transform_init_linear_to_inverse_eotf( | ||||||
| struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim, | struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim, | ||||||
| 	const uint16_t *r, const uint16_t *g, const uint16_t *b); | 	const uint16_t *r, const uint16_t *g, const uint16_t *b); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Initialize a color transformation to apply a sequence of color transforms | ||||||
|  |  * one after another. | ||||||
|  |  */ | ||||||
|  | struct wlr_color_transform *wlr_color_transform_init_pipeline( | ||||||
|  | 	struct wlr_color_transform **transforms, size_t len); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Increase the reference count of the color transform by 1. |  * Increase the reference count of the color transform by 1. | ||||||
|  */ |  */ | ||||||
|  | @ -152,4 +159,10 @@ struct wlr_color_transform *wlr_color_transform_ref(struct wlr_color_transform * | ||||||
|  */ |  */ | ||||||
| void wlr_color_transform_unref(struct wlr_color_transform *tr); | void wlr_color_transform_unref(struct wlr_color_transform *tr); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Evaluate a color transform for a given RGB triplet. | ||||||
|  |  */ | ||||||
|  | void wlr_color_transform_eval(struct wlr_color_transform *tr, | ||||||
|  | 	float out[static 3], const float in[static 3]); | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -10,6 +10,11 @@ struct wlr_gamma_control_manager_v1 { | ||||||
| 	struct wl_global *global; | 	struct wl_global *global; | ||||||
| 	struct wl_list controls; // wlr_gamma_control_v1.link
 | 	struct wl_list controls; // wlr_gamma_control_v1.link
 | ||||||
| 
 | 
 | ||||||
|  | 	// Fallback to use when an struct wlr_output doesn't support gamma LUTs.
 | ||||||
|  | 	// Can be used to apply gamma LUTs via a struct wlr_renderer. Leave zero to
 | ||||||
|  | 	// indicate that the fallback is unsupported.
 | ||||||
|  | 	size_t fallback_gamma_size; | ||||||
|  | 
 | ||||||
| 	struct { | 	struct { | ||||||
| 		struct wl_signal destroy; | 		struct wl_signal destroy; | ||||||
| 		struct wl_signal set_gamma; // struct wlr_gamma_control_manager_v1_set_gamma_event
 | 		struct wl_signal set_gamma; // struct wlr_gamma_control_manager_v1_set_gamma_event
 | ||||||
|  | @ -49,6 +54,8 @@ struct wlr_gamma_control_v1 *wlr_gamma_control_manager_v1_get_control( | ||||||
| 	struct wlr_gamma_control_manager_v1 *manager, struct wlr_output *output); | 	struct wlr_gamma_control_manager_v1 *manager, struct wlr_output *output); | ||||||
| bool wlr_gamma_control_v1_apply(struct wlr_gamma_control_v1 *gamma_control, | bool wlr_gamma_control_v1_apply(struct wlr_gamma_control_v1 *gamma_control, | ||||||
| 	struct wlr_output_state *output_state); | 	struct wlr_output_state *output_state); | ||||||
|  | struct wlr_color_transform *wlr_gamma_control_v1_get_color_transform( | ||||||
|  | 	struct wlr_gamma_control_v1 *gamma_control); | ||||||
| void wlr_gamma_control_v1_send_failed_and_destroy(struct wlr_gamma_control_v1 *gamma_control); | void wlr_gamma_control_v1_send_failed_and_destroy(struct wlr_gamma_control_v1 *gamma_control); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -267,6 +267,7 @@ struct wlr_output { | ||||||
| 	struct { | 	struct { | ||||||
| 		struct wl_listener display_destroy; | 		struct wl_listener display_destroy; | ||||||
| 		struct wlr_output_image_description image_description_value; | 		struct wlr_output_image_description image_description_value; | ||||||
|  | 		struct wlr_color_transform *color_transform; | ||||||
| 	} WLR_PRIVATE; | 	} WLR_PRIVATE; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -252,6 +252,11 @@ struct wlr_scene_output { | ||||||
| 
 | 
 | ||||||
| 		bool gamma_lut_changed; | 		bool gamma_lut_changed; | ||||||
| 		struct wlr_gamma_control_v1 *gamma_lut; | 		struct wlr_gamma_control_v1 *gamma_lut; | ||||||
|  | 		struct wlr_color_transform *gamma_lut_color_transform; | ||||||
|  | 
 | ||||||
|  | 		struct wlr_color_transform *prev_gamma_lut_color_transform; | ||||||
|  | 		struct wlr_color_transform *prev_supplied_color_transform; | ||||||
|  | 		struct wlr_color_transform *prev_combined_color_transform; | ||||||
| 
 | 
 | ||||||
| 		struct wl_listener output_commit; | 		struct wl_listener output_commit; | ||||||
| 		struct wl_listener output_damage; | 		struct wl_listener output_damage; | ||||||
|  |  | ||||||
|  | @ -164,6 +164,7 @@ struct wlr_xwm { | ||||||
| 	struct wl_listener drop_focus_destroy; | 	struct wl_listener drop_focus_destroy; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // xwm_create takes ownership of wm_fd and will close it under all circumstances.
 | ||||||
| struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd); | struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd); | ||||||
| 
 | 
 | ||||||
| void xwm_destroy(struct wlr_xwm *xwm); | void xwm_destroy(struct wlr_xwm *xwm); | ||||||
|  |  | ||||||
							
								
								
									
										121
									
								
								render/color.c
									
										
									
									
									
								
							
							
						
						
									
										121
									
								
								render/color.c
									
										
									
									
									
								
							|  | @ -62,6 +62,33 @@ struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim, | ||||||
| 	return &tx->base; | 	return &tx->base; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | struct wlr_color_transform *wlr_color_transform_init_pipeline( | ||||||
|  | 		struct wlr_color_transform **transforms, size_t len) { | ||||||
|  | 	assert(len > 0); | ||||||
|  | 
 | ||||||
|  | 	struct wlr_color_transform **copy = calloc(len, sizeof(copy[0])); | ||||||
|  | 	if (copy == NULL) { | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	struct wlr_color_transform_pipeline *tx = calloc(1, sizeof(*tx)); | ||||||
|  | 	if (!tx) { | ||||||
|  | 		free(copy); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	wlr_color_transform_init(&tx->base, COLOR_TRANSFORM_PIPELINE); | ||||||
|  | 
 | ||||||
|  | 	// TODO: flatten nested pipeline transforms
 | ||||||
|  | 	for (size_t i = 0; i < len; i++) { | ||||||
|  | 		copy[i] = wlr_color_transform_ref(transforms[i]); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	tx->transforms = copy; | ||||||
|  | 	tx->len = len; | ||||||
|  | 
 | ||||||
|  | 	return &tx->base; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void color_transform_destroy(struct wlr_color_transform *tr) { | static void color_transform_destroy(struct wlr_color_transform *tr) { | ||||||
| 	switch (tr->type) { | 	switch (tr->type) { | ||||||
| 	case COLOR_TRANSFORM_INVERSE_EOTF: | 	case COLOR_TRANSFORM_INVERSE_EOTF: | ||||||
|  | @ -73,6 +100,14 @@ static void color_transform_destroy(struct wlr_color_transform *tr) { | ||||||
| 		struct wlr_color_transform_lut_3x1d *lut_3x1d = color_transform_lut_3x1d_from_base(tr); | 		struct wlr_color_transform_lut_3x1d *lut_3x1d = color_transform_lut_3x1d_from_base(tr); | ||||||
| 		free(lut_3x1d->lut_3x1d); | 		free(lut_3x1d->lut_3x1d); | ||||||
| 		break; | 		break; | ||||||
|  | 	case COLOR_TRANSFORM_PIPELINE:; | ||||||
|  | 		struct wlr_color_transform_pipeline *pipeline = | ||||||
|  | 			wl_container_of(tr, pipeline, base); | ||||||
|  | 		for (size_t i = 0; i < pipeline->len; i++) { | ||||||
|  | 			wlr_color_transform_unref(pipeline->transforms[i]); | ||||||
|  | 		} | ||||||
|  | 		free(pipeline->transforms); | ||||||
|  | 		break; | ||||||
| 	} | 	} | ||||||
| 	wlr_addon_set_finish(&tr->addons); | 	wlr_addon_set_finish(&tr->addons); | ||||||
| 	free(tr); | 	free(tr); | ||||||
|  | @ -108,6 +143,65 @@ struct wlr_color_transform_lut_3x1d *color_transform_lut_3x1d_from_base( | ||||||
| 	return lut_3x1d; | 	return lut_3x1d; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static float srgb_eval_inverse_eotf(float x) { | ||||||
|  | 	// See https://www.w3.org/Graphics/Color/srgb
 | ||||||
|  | 	if (x <= 0.0031308) { | ||||||
|  | 		return 12.92 * x; | ||||||
|  | 	} else { | ||||||
|  | 		return 1.055 * powf(x, 1.0 / 2.4) - 0.055; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static float st2084_pq_eval_inverse_eotf(float x) { | ||||||
|  | 	// H.273 TransferCharacteristics code point 16
 | ||||||
|  | 	float c1 = 0.8359375; | ||||||
|  | 	float c2 = 18.8515625; | ||||||
|  | 	float c3 = 18.6875; | ||||||
|  | 	float m = 78.84375; | ||||||
|  | 	float n = 0.1593017578125; | ||||||
|  | 	if (x < 0) { | ||||||
|  | 		x = 0; | ||||||
|  | 	} | ||||||
|  | 	if (x > 1) { | ||||||
|  | 		x = 1; | ||||||
|  | 	} | ||||||
|  | 	float pow_n = powf(x, n); | ||||||
|  | 	return powf((c1 + c2 * pow_n) / (1 + c3 * pow_n), m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static float bt1886_eval_inverse_eotf(float x) { | ||||||
|  | 	float lb = powf(0.0001, 1.0 / 2.4); | ||||||
|  | 	float lw = powf(1.0, 1.0 / 2.4); | ||||||
|  | 	float a  = powf(lw - lb, 2.4); | ||||||
|  | 	float b  = lb / (lw - lb); | ||||||
|  | 	return powf(x / a, 1.0 / 2.4) - b; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static float transfer_function_eval_inverse_eotf( | ||||||
|  | 		enum wlr_color_transfer_function tf, float x) { | ||||||
|  | 	switch (tf) { | ||||||
|  | 	case WLR_COLOR_TRANSFER_FUNCTION_SRGB: | ||||||
|  | 		return srgb_eval_inverse_eotf(x); | ||||||
|  | 	case WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ: | ||||||
|  | 		return st2084_pq_eval_inverse_eotf(x); | ||||||
|  | 	case WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR: | ||||||
|  | 		return x; | ||||||
|  | 	case WLR_COLOR_TRANSFER_FUNCTION_GAMMA22: | ||||||
|  | 		return powf(x, 1.0 / 2.2); | ||||||
|  | 	case WLR_COLOR_TRANSFER_FUNCTION_BT1886: | ||||||
|  | 		return bt1886_eval_inverse_eotf(x); | ||||||
|  | 	} | ||||||
|  | 	abort(); // unreachable
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void color_transform_inverse_eotf_eval( | ||||||
|  | 		struct wlr_color_transform_inverse_eotf *tr, | ||||||
|  | 		float out[static 3], const float in[static 3]) { | ||||||
|  | 	for (size_t i = 0; i < 3; i++) { | ||||||
|  | 		out[i] = transfer_function_eval_inverse_eotf(tr->tf, in[i]); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static float lut_1d_get(const uint16_t *lut, size_t len, size_t i) { | static float lut_1d_get(const uint16_t *lut, size_t len, size_t i) { | ||||||
| 	if (i >= len) { | 	if (i >= len) { | ||||||
| 		i = len - 1; | 		i = len - 1; | ||||||
|  | @ -125,13 +219,38 @@ static float lut_1d_eval(const uint16_t *lut, size_t len, float x) { | ||||||
| 	return a * (1 - frac_part) + b * frac_part; | 	return a * (1 - frac_part) + b * frac_part; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void color_transform_lut_3x1d_eval(struct wlr_color_transform_lut_3x1d *tr, | static void color_transform_lut_3x1d_eval(struct wlr_color_transform_lut_3x1d *tr, | ||||||
| 		float out[static 3], const float in[static 3]) { | 		float out[static 3], const float in[static 3]) { | ||||||
| 	for (size_t i = 0; i < 3; i++) { | 	for (size_t i = 0; i < 3; i++) { | ||||||
| 		out[i] = lut_1d_eval(&tr->lut_3x1d[tr->dim * i], tr->dim, in[i]); | 		out[i] = lut_1d_eval(&tr->lut_3x1d[tr->dim * i], tr->dim, in[i]); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void wlr_color_transform_eval(struct wlr_color_transform *tr, | ||||||
|  | 		float out[static 3], const float in[static 3]) { | ||||||
|  | 	switch (tr->type) { | ||||||
|  | 	case COLOR_TRANSFORM_INVERSE_EOTF: | ||||||
|  | 		color_transform_inverse_eotf_eval(wlr_color_transform_inverse_eotf_from_base(tr), out, in); | ||||||
|  | 		break; | ||||||
|  | 	case COLOR_TRANSFORM_LCMS2: | ||||||
|  | 		color_transform_lcms2_eval(color_transform_lcms2_from_base(tr), out, in); | ||||||
|  | 		break; | ||||||
|  | 	case COLOR_TRANSFORM_LUT_3X1D: | ||||||
|  | 		color_transform_lut_3x1d_eval(color_transform_lut_3x1d_from_base(tr), out, in); | ||||||
|  | 		break; | ||||||
|  | 	case COLOR_TRANSFORM_PIPELINE:; | ||||||
|  | 		struct wlr_color_transform_pipeline *pipeline = | ||||||
|  | 			wl_container_of(tr, pipeline, base); | ||||||
|  | 		float color[3]; | ||||||
|  | 		memcpy(color, in, sizeof(color)); | ||||||
|  | 		for (size_t i = 0; i < pipeline->len; i++) { | ||||||
|  | 			wlr_color_transform_eval(pipeline->transforms[i], color, color); | ||||||
|  | 		} | ||||||
|  | 		memcpy(out, color, sizeof(color)); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void wlr_color_primaries_from_named(struct wlr_color_primaries *out, | void wlr_color_primaries_from_named(struct wlr_color_primaries *out, | ||||||
| 		enum wlr_color_named_primaries named) { | 		enum wlr_color_named_primaries named) { | ||||||
| 	switch (named) { | 	switch (named) { | ||||||
|  |  | ||||||
|  | @ -964,19 +964,6 @@ static bool create_3d_lut_image(struct wlr_vk_renderer *renderer, | ||||||
| 	*ds = VK_NULL_HANDLE; | 	*ds = VK_NULL_HANDLE; | ||||||
| 	*ds_pool = NULL; | 	*ds_pool = NULL; | ||||||
| 
 | 
 | ||||||
| 	struct wlr_color_transform_lcms2 *tr_lcms2 = NULL; |  | ||||||
| 	struct wlr_color_transform_lut_3x1d *tr_lut_3x1d = NULL; |  | ||||||
| 	switch (tr->type) { |  | ||||||
| 	case COLOR_TRANSFORM_INVERSE_EOTF: |  | ||||||
| 		abort(); // unreachable
 |  | ||||||
| 	case COLOR_TRANSFORM_LCMS2: |  | ||||||
| 		tr_lcms2 = color_transform_lcms2_from_base(tr); |  | ||||||
| 		break; |  | ||||||
| 	case COLOR_TRANSFORM_LUT_3X1D: |  | ||||||
| 		tr_lut_3x1d = color_transform_lut_3x1d_from_base(tr); |  | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// R32G32B32 is not a required Vulkan format
 | 	// R32G32B32 is not a required Vulkan format
 | ||||||
| 	// TODO: use it when available
 | 	// TODO: use it when available
 | ||||||
| 	VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT; | 	VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT; | ||||||
|  | @ -1074,11 +1061,7 @@ static bool create_3d_lut_image(struct wlr_vk_renderer *renderer, | ||||||
| 					b_index * sample_range, | 					b_index * sample_range, | ||||||
| 				}; | 				}; | ||||||
| 				float rgb_out[3]; | 				float rgb_out[3]; | ||||||
| 				if (tr_lcms2 != NULL) { | 				wlr_color_transform_eval(tr, rgb_out, rgb_in); | ||||||
| 					color_transform_lcms2_eval(tr_lcms2, rgb_out, rgb_in); |  | ||||||
| 				} else { |  | ||||||
| 					color_transform_lut_3x1d_eval(tr_lut_3x1d, rgb_out, rgb_in); |  | ||||||
| 				} |  | ||||||
| 
 | 
 | ||||||
| 				dst[dst_offset] = rgb_out[0]; | 				dst[dst_offset] = rgb_out[0]; | ||||||
| 				dst[dst_offset + 1] = rgb_out[1]; | 				dst[dst_offset + 1] = rgb_out[1]; | ||||||
|  |  | ||||||
|  | @ -242,6 +242,15 @@ static void output_apply_state(struct wlr_output *output, | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (state->committed & WLR_OUTPUT_STATE_COLOR_TRANSFORM) { | ||||||
|  | 		wlr_color_transform_unref(output->color_transform); | ||||||
|  | 		if (state->color_transform != NULL) { | ||||||
|  | 			output->color_transform = wlr_color_transform_ref(state->color_transform); | ||||||
|  | 		} else { | ||||||
|  | 			output->color_transform = NULL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	bool geometry_updated = state->committed & | 	bool geometry_updated = state->committed & | ||||||
| 		(WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM | | 		(WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM | | ||||||
| 		WLR_OUTPUT_STATE_SUBPIXEL); | 		WLR_OUTPUT_STATE_SUBPIXEL); | ||||||
|  | @ -407,6 +416,7 @@ void wlr_output_finish(struct wlr_output *output) { | ||||||
| 
 | 
 | ||||||
| 	wlr_swapchain_destroy(output->cursor_swapchain); | 	wlr_swapchain_destroy(output->cursor_swapchain); | ||||||
| 	wlr_buffer_unlock(output->cursor_front_buffer); | 	wlr_buffer_unlock(output->cursor_front_buffer); | ||||||
|  | 	wlr_color_transform_unref(output->color_transform); | ||||||
| 
 | 
 | ||||||
| 	wlr_swapchain_destroy(output->swapchain); | 	wlr_swapchain_destroy(output->swapchain); | ||||||
| 
 | 
 | ||||||
|  | @ -515,8 +525,7 @@ const struct wlr_output_image_description *output_pending_image_description( | ||||||
|  * Returns a bitfield of the unchanged fields. |  * Returns a bitfield of the unchanged fields. | ||||||
|  * |  * | ||||||
|  * Some fields are not checked: damage always changes in-between frames, the |  * Some fields are not checked: damage always changes in-between frames, the | ||||||
|  * gamma LUT is too expensive to check, the contents of the buffer might have |  * contents of the buffer might have changed, etc. | ||||||
|  * changed, etc. |  | ||||||
|  */ |  */ | ||||||
| static uint32_t output_compare_state(struct wlr_output *output, | static uint32_t output_compare_state(struct wlr_output *output, | ||||||
| 		const struct wlr_output_state *state) { | 		const struct wlr_output_state *state) { | ||||||
|  | @ -562,6 +571,10 @@ static uint32_t output_compare_state(struct wlr_output *output, | ||||||
| 			output->subpixel == state->subpixel) { | 			output->subpixel == state->subpixel) { | ||||||
| 		fields |= WLR_OUTPUT_STATE_SUBPIXEL; | 		fields |= WLR_OUTPUT_STATE_SUBPIXEL; | ||||||
| 	} | 	} | ||||||
|  | 	if ((state->committed & WLR_OUTPUT_STATE_COLOR_TRANSFORM) && | ||||||
|  | 			output->color_transform == state->color_transform) { | ||||||
|  | 		fields |= WLR_OUTPUT_STATE_COLOR_TRANSFORM; | ||||||
|  | 	} | ||||||
| 	return fields; | 	return fields; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1530,6 +1530,8 @@ static void scene_handle_gamma_control_manager_v1_set_gamma(struct wl_listener * | ||||||
| 
 | 
 | ||||||
| 	output->gamma_lut_changed = true; | 	output->gamma_lut_changed = true; | ||||||
| 	output->gamma_lut = event->control; | 	output->gamma_lut = event->control; | ||||||
|  | 	wlr_color_transform_unref(output->gamma_lut_color_transform); | ||||||
|  | 	output->gamma_lut_color_transform = wlr_gamma_control_v1_get_color_transform(event->control); | ||||||
| 	wlr_output_schedule_frame(output->output); | 	wlr_output_schedule_frame(output->output); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1547,6 +1549,8 @@ static void scene_handle_gamma_control_manager_v1_destroy(struct wl_listener *li | ||||||
| 	wl_list_for_each(output, &scene->outputs, link) { | 	wl_list_for_each(output, &scene->outputs, link) { | ||||||
| 		output->gamma_lut_changed = false; | 		output->gamma_lut_changed = false; | ||||||
| 		output->gamma_lut = NULL; | 		output->gamma_lut = NULL; | ||||||
|  | 		wlr_color_transform_unref(output->gamma_lut_color_transform); | ||||||
|  | 		output->gamma_lut_color_transform = NULL; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1766,6 +1770,10 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { | ||||||
| 	wl_list_remove(&scene_output->output_damage.link); | 	wl_list_remove(&scene_output->output_damage.link); | ||||||
| 	wl_list_remove(&scene_output->output_needs_frame.link); | 	wl_list_remove(&scene_output->output_needs_frame.link); | ||||||
| 	wlr_drm_syncobj_timeline_unref(scene_output->in_timeline); | 	wlr_drm_syncobj_timeline_unref(scene_output->in_timeline); | ||||||
|  | 	wlr_color_transform_unref(scene_output->gamma_lut_color_transform); | ||||||
|  | 	wlr_color_transform_unref(scene_output->prev_gamma_lut_color_transform); | ||||||
|  | 	wlr_color_transform_unref(scene_output->prev_supplied_color_transform); | ||||||
|  | 	wlr_color_transform_unref(scene_output->prev_combined_color_transform); | ||||||
| 	wl_array_release(&scene_output->render_list); | 	wl_array_release(&scene_output->render_list); | ||||||
| 	free(scene_output); | 	free(scene_output); | ||||||
| } | } | ||||||
|  | @ -2104,16 +2112,15 @@ static void scene_output_state_attempt_gamma(struct wlr_scene_output *scene_outp | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!wlr_gamma_control_v1_apply(scene_output->gamma_lut, &gamma_pending)) { | 	wlr_output_state_set_color_transform(&gamma_pending, scene_output->gamma_lut_color_transform); | ||||||
| 		wlr_output_state_finish(&gamma_pending); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	scene_output->gamma_lut_changed = false; | 	scene_output->gamma_lut_changed = false; | ||||||
|  | 
 | ||||||
| 	if (!wlr_output_test_state(scene_output->output, &gamma_pending)) { | 	if (!wlr_output_test_state(scene_output->output, &gamma_pending)) { | ||||||
| 		wlr_gamma_control_v1_send_failed_and_destroy(scene_output->gamma_lut); | 		wlr_gamma_control_v1_send_failed_and_destroy(scene_output->gamma_lut); | ||||||
| 
 | 
 | ||||||
| 		scene_output->gamma_lut = NULL; | 		scene_output->gamma_lut = NULL; | ||||||
|  | 		wlr_color_transform_unref(scene_output->gamma_lut_color_transform); | ||||||
|  | 		scene_output->gamma_lut_color_transform = NULL; | ||||||
| 		wlr_output_state_finish(&gamma_pending); | 		wlr_output_state_finish(&gamma_pending); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | @ -2122,6 +2129,41 @@ static void scene_output_state_attempt_gamma(struct wlr_scene_output *scene_outp | ||||||
| 	wlr_output_state_finish(&gamma_pending); | 	wlr_output_state_finish(&gamma_pending); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static struct wlr_color_transform *scene_output_combine_color_transforms( | ||||||
|  | 		struct wlr_scene_output *scene_output, struct wlr_color_transform *supplied) { | ||||||
|  | 	struct wlr_color_transform *gamma_lut = scene_output->gamma_lut_color_transform; | ||||||
|  | 	assert(gamma_lut != NULL); | ||||||
|  | 
 | ||||||
|  | 	if (gamma_lut == scene_output->prev_gamma_lut_color_transform && | ||||||
|  | 			supplied == scene_output->prev_supplied_color_transform) { | ||||||
|  | 		return wlr_color_transform_ref(scene_output->prev_combined_color_transform); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	struct wlr_color_transform *combined; | ||||||
|  | 	if (supplied == NULL) { | ||||||
|  | 		combined = wlr_color_transform_ref(gamma_lut); | ||||||
|  | 	} else { | ||||||
|  | 		struct wlr_color_transform *transforms[] = { | ||||||
|  | 			gamma_lut, | ||||||
|  | 			supplied, | ||||||
|  | 		}; | ||||||
|  | 		size_t transforms_len = sizeof(transforms) / sizeof(transforms[0]); | ||||||
|  | 		combined = wlr_color_transform_init_pipeline(transforms, transforms_len); | ||||||
|  | 		if (combined == NULL) { | ||||||
|  | 			return NULL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	wlr_color_transform_unref(scene_output->prev_gamma_lut_color_transform); | ||||||
|  | 	scene_output->prev_gamma_lut_color_transform = wlr_color_transform_ref(gamma_lut); | ||||||
|  | 	wlr_color_transform_unref(scene_output->prev_supplied_color_transform); | ||||||
|  | 	scene_output->prev_supplied_color_transform = supplied ? wlr_color_transform_ref(supplied) : NULL; | ||||||
|  | 	wlr_color_transform_unref(scene_output->prev_combined_color_transform); | ||||||
|  | 	scene_output->prev_combined_color_transform = wlr_color_transform_ref(combined); | ||||||
|  | 
 | ||||||
|  | 	return combined; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, | bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, | ||||||
| 		struct wlr_output_state *state, const struct wlr_scene_output_state_options *options) { | 		struct wlr_output_state *state, const struct wlr_scene_output_state_options *options) { | ||||||
| 	struct wlr_scene_output_state_options default_options = {0}; | 	struct wlr_scene_output_state_options default_options = {0}; | ||||||
|  | @ -2145,6 +2187,16 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, | ||||||
| 	enum wlr_scene_debug_damage_option debug_damage = | 	enum wlr_scene_debug_damage_option debug_damage = | ||||||
| 		scene_output->scene->debug_damage_option; | 		scene_output->scene->debug_damage_option; | ||||||
| 
 | 
 | ||||||
|  | 	bool render_gamma_lut = false; | ||||||
|  | 	if (wlr_output_get_gamma_size(output) == 0 && output->renderer->features.output_color_transform) { | ||||||
|  | 		if (scene_output->gamma_lut_color_transform != scene_output->prev_gamma_lut_color_transform) { | ||||||
|  | 			scene_output_damage_whole(scene_output); | ||||||
|  | 		} | ||||||
|  | 		if (scene_output->gamma_lut_color_transform != NULL) { | ||||||
|  | 			render_gamma_lut = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	struct render_data render_data = { | 	struct render_data render_data = { | ||||||
| 		.transform = output->transform, | 		.transform = output->transform, | ||||||
| 		.scale = output->scale, | 		.scale = output->scale, | ||||||
|  | @ -2245,7 +2297,7 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, | ||||||
| 	// - There are no color transforms that need to be applied
 | 	// - There are no color transforms that need to be applied
 | ||||||
| 	// - Damage highlight debugging is not enabled
 | 	// - Damage highlight debugging is not enabled
 | ||||||
| 	enum scene_direct_scanout_result scanout_result = SCANOUT_INELIGIBLE; | 	enum scene_direct_scanout_result scanout_result = SCANOUT_INELIGIBLE; | ||||||
| 	if (options->color_transform == NULL && list_len == 1 | 	if (options->color_transform == NULL && !render_gamma_lut && list_len == 1 | ||||||
| 			&& debug_damage != WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT) { | 			&& debug_damage != WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT) { | ||||||
| 		scanout_result = scene_entry_try_direct_scanout(&list_data[0], state, &render_data); | 		scanout_result = scene_entry_try_direct_scanout(&list_data[0], state, &render_data); | ||||||
| 	} | 	} | ||||||
|  | @ -2319,6 +2371,17 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, | ||||||
| 		color_transform = wlr_color_transform_ref(options->color_transform); | 		color_transform = wlr_color_transform_ref(options->color_transform); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (render_gamma_lut) { | ||||||
|  | 		struct wlr_color_transform *combined = | ||||||
|  | 			scene_output_combine_color_transforms(scene_output, color_transform); | ||||||
|  | 		wlr_color_transform_unref(color_transform); | ||||||
|  | 		if (combined == NULL) { | ||||||
|  | 			wlr_buffer_unlock(buffer); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		color_transform = combined; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	scene_output->in_point++; | 	scene_output->in_point++; | ||||||
| 	struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass(output->renderer, buffer, | 	struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass(output->renderer, buffer, | ||||||
| 			&(struct wlr_buffer_pass_options){ | 			&(struct wlr_buffer_pass_options){ | ||||||
|  | @ -2441,7 +2504,9 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, | ||||||
| 			scene_output->in_point); | 			scene_output->in_point); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	scene_output_state_attempt_gamma(scene_output, state); | 	if (!render_gamma_lut) { | ||||||
|  | 		scene_output_state_attempt_gamma(scene_output, state); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -157,6 +157,9 @@ static void gamma_control_manager_get_gamma_control(struct wl_client *client, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	size_t gamma_size = wlr_output_get_gamma_size(output); | 	size_t gamma_size = wlr_output_get_gamma_size(output); | ||||||
|  | 	if (gamma_size == 0) { | ||||||
|  | 		gamma_size = manager->fallback_gamma_size; | ||||||
|  | 	} | ||||||
| 	if (gamma_size == 0) { | 	if (gamma_size == 0) { | ||||||
| 		zwlr_gamma_control_v1_send_failed(resource); | 		zwlr_gamma_control_v1_send_failed(resource); | ||||||
| 		return; | 		return; | ||||||
|  | @ -262,15 +265,24 @@ struct wlr_gamma_control_v1 *wlr_gamma_control_manager_v1_get_control( | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | struct wlr_color_transform *wlr_gamma_control_v1_get_color_transform( | ||||||
|  | 		struct wlr_gamma_control_v1 *gamma_control) { | ||||||
|  | 	if (gamma_control == NULL || gamma_control->table == NULL) { | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const uint16_t *r = gamma_control->table; | ||||||
|  | 	const uint16_t *g = gamma_control->table + gamma_control->ramp_size; | ||||||
|  | 	const uint16_t *b = gamma_control->table + 2 * gamma_control->ramp_size; | ||||||
|  | 
 | ||||||
|  | 	return wlr_color_transform_init_lut_3x1d(gamma_control->ramp_size, r, g, b); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool wlr_gamma_control_v1_apply(struct wlr_gamma_control_v1 *gamma_control, | bool wlr_gamma_control_v1_apply(struct wlr_gamma_control_v1 *gamma_control, | ||||||
| 		struct wlr_output_state *output_state) { | 		struct wlr_output_state *output_state) { | ||||||
| 	struct wlr_color_transform *tr = NULL; | 	struct wlr_color_transform *tr = NULL; | ||||||
| 	if (gamma_control != NULL && gamma_control->table != NULL) { | 	if (gamma_control != NULL && gamma_control->table != NULL) { | ||||||
| 		const uint16_t *r = gamma_control->table; | 		tr = wlr_gamma_control_v1_get_color_transform(gamma_control); | ||||||
| 		const uint16_t *g = gamma_control->table + gamma_control->ramp_size; |  | ||||||
| 		const uint16_t *b = gamma_control->table + 2 * gamma_control->ramp_size; |  | ||||||
| 
 |  | ||||||
| 		tr = wlr_color_transform_init_lut_3x1d(gamma_control->ramp_size, r, g, b); |  | ||||||
| 		if (tr == NULL) { | 		if (tr == NULL) { | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -56,6 +56,7 @@ static void input_method_destroy(struct wlr_input_method_v2 *input_method) { | ||||||
| 			popup_surface, tmp, &input_method->popup_surfaces, link) { | 			popup_surface, tmp, &input_method->popup_surfaces, link) { | ||||||
| 		popup_surface_destroy(popup_surface); | 		popup_surface_destroy(popup_surface); | ||||||
| 	} | 	} | ||||||
|  | 	wlr_input_method_keyboard_grab_v2_destroy(input_method->keyboard_grab); | ||||||
| 	wl_signal_emit_mutable(&input_method->events.destroy, NULL); | 	wl_signal_emit_mutable(&input_method->events.destroy, NULL); | ||||||
| 
 | 
 | ||||||
| 	assert(wl_list_empty(&input_method->events.commit.listener_list)); | 	assert(wl_list_empty(&input_method->events.commit.listener_list)); | ||||||
|  | @ -65,7 +66,6 @@ static void input_method_destroy(struct wlr_input_method_v2 *input_method) { | ||||||
| 
 | 
 | ||||||
| 	wl_list_remove(wl_resource_get_link(input_method->resource)); | 	wl_list_remove(wl_resource_get_link(input_method->resource)); | ||||||
| 	wl_list_remove(&input_method->seat_client_destroy.link); | 	wl_list_remove(&input_method->seat_client_destroy.link); | ||||||
| 	wlr_input_method_keyboard_grab_v2_destroy(input_method->keyboard_grab); |  | ||||||
| 	input_state_reset(&input_method->pending); | 	input_state_reset(&input_method->pending); | ||||||
| 	input_state_reset(&input_method->current); | 	input_state_reset(&input_method->current); | ||||||
| 	free(input_method); | 	free(input_method); | ||||||
|  | @ -271,8 +271,7 @@ void wlr_input_method_keyboard_grab_v2_destroy( | ||||||
| 	if (!keyboard_grab) { | 	if (!keyboard_grab) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	wl_signal_emit_mutable(&keyboard_grab->events.destroy, keyboard_grab); | 	wl_signal_emit_mutable(&keyboard_grab->events.destroy, NULL); | ||||||
| 
 |  | ||||||
| 	assert(wl_list_empty(&keyboard_grab->events.destroy.listener_list)); | 	assert(wl_list_empty(&keyboard_grab->events.destroy.listener_list)); | ||||||
| 
 | 
 | ||||||
| 	keyboard_grab->input_method->keyboard_grab = NULL; | 	keyboard_grab->input_method->keyboard_grab = NULL; | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ struct wlr_linux_drm_syncobj_surface_v1 { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct wlr_linux_drm_syncobj_surface_v1_commit { | struct wlr_linux_drm_syncobj_surface_v1_commit { | ||||||
| 	struct wlr_linux_drm_syncobj_surface_v1 *surface; | 	struct wlr_surface *surface; | ||||||
| 	struct wlr_drm_syncobj_timeline_waiter waiter; | 	struct wlr_drm_syncobj_timeline_waiter waiter; | ||||||
| 	uint32_t cached_seq; | 	uint32_t cached_seq; | ||||||
| 
 | 
 | ||||||
|  | @ -192,7 +192,7 @@ static struct wlr_linux_drm_syncobj_surface_v1 *surface_from_wlr_surface( | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void surface_commit_destroy(struct wlr_linux_drm_syncobj_surface_v1_commit *commit) { | static void surface_commit_destroy(struct wlr_linux_drm_syncobj_surface_v1_commit *commit) { | ||||||
| 	wlr_surface_unlock_cached(commit->surface->surface, commit->cached_seq); | 	wlr_surface_unlock_cached(commit->surface, commit->cached_seq); | ||||||
| 	wl_list_remove(&commit->surface_destroy.link); | 	wl_list_remove(&commit->surface_destroy.link); | ||||||
| 	wlr_drm_syncobj_timeline_waiter_finish(&commit->waiter); | 	wlr_drm_syncobj_timeline_waiter_finish(&commit->waiter); | ||||||
| 	free(commit); | 	free(commit); | ||||||
|  | @ -237,7 +237,7 @@ static bool lock_surface_commit(struct wlr_linux_drm_syncobj_surface_v1 *surface | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	commit->surface = surface; | 	commit->surface = surface->surface; | ||||||
| 	commit->cached_seq = wlr_surface_lock_pending(surface->surface); | 	commit->cached_seq = wlr_surface_lock_pending(surface->surface); | ||||||
| 
 | 
 | ||||||
| 	commit->surface_destroy.notify = surface_commit_handle_surface_destroy; | 	commit->surface_destroy.notify = surface_commit_handle_surface_destroy; | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								util/box.c
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								util/box.c
									
										
									
									
									
								
							|  | @ -19,16 +19,15 @@ void wlr_box_closest_point(const struct wlr_box *box, double x, double y, | ||||||
| 	//
 | 	//
 | ||||||
| 	// In order to be consistent with e.g. wlr_box_contains_point(),
 | 	// In order to be consistent with e.g. wlr_box_contains_point(),
 | ||||||
| 	// this function returns a point inside the bottom and right edges
 | 	// this function returns a point inside the bottom and right edges
 | ||||||
| 	// of the box by at least 1/65536 of a unit (pixel). 1/65536 is
 | 	// of the box by at least 1/256 of a unit (pixel). 1/256 is
 | ||||||
| 	// small enough to avoid a "dead zone" with high-resolution mice
 | 	// small enough to avoid a "dead zone" with high-resolution mice
 | ||||||
| 	// but large enough to avoid rounding to zero (due to loss of
 | 	// but large enough to avoid rounding to zero in wl_fixed_from_double().
 | ||||||
| 	// significant digits) in simple floating-point calculations.
 |  | ||||||
| 
 | 
 | ||||||
| 	// find the closest x point
 | 	// find the closest x point
 | ||||||
| 	if (x < box->x) { | 	if (x < box->x) { | ||||||
| 		*dest_x = box->x; | 		*dest_x = box->x; | ||||||
| 	} else if (x > box->x + box->width - 1/65536.0) { | 	} else if (x > box->x + box->width - 1/256.0) { | ||||||
| 		*dest_x = box->x + box->width - 1/65536.0; | 		*dest_x = box->x + box->width - 1/256.0; | ||||||
| 	} else { | 	} else { | ||||||
| 		*dest_x = x; | 		*dest_x = x; | ||||||
| 	} | 	} | ||||||
|  | @ -36,8 +35,8 @@ void wlr_box_closest_point(const struct wlr_box *box, double x, double y, | ||||||
| 	// find closest y point
 | 	// find closest y point
 | ||||||
| 	if (y < box->y) { | 	if (y < box->y) { | ||||||
| 		*dest_y = box->y; | 		*dest_y = box->y; | ||||||
| 	} else if (y > box->y + box->height - 1/65536.0) { | 	} else if (y > box->y + box->height - 1/256.0) { | ||||||
| 		*dest_y = box->y + box->height - 1/65536.0; | 		*dest_y = box->y + box->height - 1/256.0; | ||||||
| 	} else { | 	} else { | ||||||
| 		*dest_y = y; | 		*dest_y = y; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -42,6 +42,9 @@ static void handle_server_start(struct wl_listener *listener, void *data) { | ||||||
| static void xwayland_mark_ready(struct wlr_xwayland *xwayland) { | static void xwayland_mark_ready(struct wlr_xwayland *xwayland) { | ||||||
| 	assert(xwayland->server->wm_fd[0] >= 0); | 	assert(xwayland->server->wm_fd[0] >= 0); | ||||||
| 	xwayland->xwm = xwm_create(xwayland, xwayland->server->wm_fd[0]); | 	xwayland->xwm = xwm_create(xwayland, xwayland->server->wm_fd[0]); | ||||||
|  | 	// xwm_create takes ownership of wm_fd[0] under all circumstances
 | ||||||
|  | 	xwayland->server->wm_fd[0] = -1; | ||||||
|  | 
 | ||||||
| 	if (!xwayland->xwm) { | 	if (!xwayland->xwm) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -2530,6 +2530,7 @@ void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride, | ||||||
| struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) { | struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) { | ||||||
| 	struct wlr_xwm *xwm = calloc(1, sizeof(*xwm)); | 	struct wlr_xwm *xwm = calloc(1, sizeof(*xwm)); | ||||||
| 	if (xwm == NULL) { | 	if (xwm == NULL) { | ||||||
|  | 		close(wm_fd); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -2544,11 +2545,13 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) { | ||||||
| 
 | 
 | ||||||
| 	xwm->ping_timeout = 10000; | 	xwm->ping_timeout = 10000; | ||||||
| 
 | 
 | ||||||
|  | 	// xcb_connect_to_fd takes ownership of the FD regardless of success/failure
 | ||||||
| 	xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL); | 	xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL); | ||||||
| 
 | 
 | ||||||
| 	int rc = xcb_connection_has_error(xwm->xcb_conn); | 	int rc = xcb_connection_has_error(xwm->xcb_conn); | ||||||
| 	if (rc) { | 	if (rc) { | ||||||
| 		wlr_log(WLR_ERROR, "xcb connect failed: %d", rc); | 		wlr_log(WLR_ERROR, "xcb connect failed: %d", rc); | ||||||
|  | 		xcb_disconnect(xwm->xcb_conn); | ||||||
| 		free(xwm); | 		free(xwm); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
|  | @ -2745,6 +2748,22 @@ bool xwm_atoms_contains(struct wlr_xwm *xwm, xcb_atom_t *atoms, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface) { | void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface) { | ||||||
|  | 	if (surface->pinging) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// don't ping if client not supports
 | ||||||
|  | 	bool supports_ping = false; | ||||||
|  | 	for(size_t i = 0; i < surface->protocols_len; i++) { | ||||||
|  | 		if (surface->protocols[i] == surface->xwm->atoms[NET_WM_PING]) { | ||||||
|  | 			supports_ping = true; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (!supports_ping) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	xcb_client_message_data_t data = { 0 }; | 	xcb_client_message_data_t data = { 0 }; | ||||||
| 	data.data32[0] = surface->xwm->atoms[NET_WM_PING]; | 	data.data32[0] = surface->xwm->atoms[NET_WM_PING]; | ||||||
| 	data.data32[1] = XCB_CURRENT_TIME; | 	data.data32[1] = XCB_CURRENT_TIME; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue