-
Notifications
You must be signed in to change notification settings - Fork 3.2k
vo_gpu_next: set color directly using Wayland protocol #17345
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
170c5a0
eb1d839
c0f21a5
d61b80e
463c7c9
cf06281
7fa9c8e
71910a7
d40f956
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2029,6 +2029,10 @@ static void supported_feature(void *data, struct wp_color_manager_v1 *color_mana | |||||||||
| MP_VERBOSE(wl, "Compositor supports setting mastering display primaries.\n"); | ||||||||||
| wl->supports_display_primaries = true; | ||||||||||
| break; | ||||||||||
| case WP_COLOR_MANAGER_V1_FEATURE_SET_LUMINANCES: | ||||||||||
| MP_VERBOSE(wl, "Compositor supports setting primary color luminances.\n"); | ||||||||||
| wl->supports_set_luminances = true; | ||||||||||
| break; | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
|
|
@@ -2144,20 +2148,31 @@ static void info_done(void *data, struct wp_image_description_info_v1 *image_des | |||||||||
| if (!wd->icc_file) { | ||||||||||
| MP_VERBOSE(wl, "Preferred surface feedback received:\n"); | ||||||||||
| log_color_space(wl->log, wd); | ||||||||||
| // We don't support extended ranges output where luminance exceeds | ||||||||||
| // maximum nominal luminance range (1.0), so switch to PQ. | ||||||||||
| if (fabsf(wd->csp.hdr.max_luma / wd->ref_luma - 1.0f) > 1e-4f && | ||||||||||
| !pl_color_transfer_is_hdr(wd->csp.transfer)) { | ||||||||||
| MP_VERBOSE(wl, "Setting preferred transfer to PQ for HDR output.\n"); | ||||||||||
| wd->csp.transfer = PL_COLOR_TRC_PQ; | ||||||||||
| } | ||||||||||
| // Wayland luminances are always in reference to the reference luminance. That is, | ||||||||||
| // if max_luma == 2*ref_luma, then there is 2x headroom above paper white. On the | ||||||||||
| // other hand, libplacebo hardcodes PL_COLOR_SDR_WHITE as the reference luminance. | ||||||||||
| // We must scale all wayland values to correspond to the libplacebo scale, | ||||||||||
| // otherwise libplacebo will assume that there is too little or too much headroom | ||||||||||
| // when ref_luma != PL_COLOR_SDR_WHITE. | ||||||||||
| float a = wd->min_luma; | ||||||||||
| float b = (PL_COLOR_SDR_WHITE - PL_COLOR_HDR_BLACK) / (wd->ref_luma - a); | ||||||||||
| wd->csp.hdr.min_luma = (wd->csp.hdr.min_luma - a) * b + PL_COLOR_HDR_BLACK; | ||||||||||
| wd->csp.hdr.max_luma = (wd->csp.hdr.max_luma - a) * b + PL_COLOR_HDR_BLACK; | ||||||||||
| // Wayland treats all transfers as display referred, don't scale min | ||||||||||
| // luminance, and hope compositors will do the right thing mapping it, | ||||||||||
| // or to be specific, not mapping it, because we set the same value. | ||||||||||
| float c = wd->min_luma; | ||||||||||
| float b = (PL_COLOR_SDR_WHITE - c) / (wd->ref_luma - a); | ||||||||||
| wd->csp.hdr.min_luma = (wd->csp.hdr.min_luma - a) * b + c; | ||||||||||
| wd->csp.hdr.max_luma = (wd->csp.hdr.max_luma - a) * b + c; | ||||||||||
| if (wd->csp.hdr.max_cll != 0) | ||||||||||
| wd->csp.hdr.max_cll = (wd->csp.hdr.max_cll - a) * b + PL_COLOR_HDR_BLACK; | ||||||||||
| wd->csp.hdr.max_cll = (wd->csp.hdr.max_cll - a) * b + c; | ||||||||||
| if (wd->csp.hdr.max_fall != 0) | ||||||||||
| wd->csp.hdr.max_fall = (wd->csp.hdr.max_fall - a) * b + PL_COLOR_HDR_BLACK; | ||||||||||
| wd->csp.hdr.max_fall = (wd->csp.hdr.max_fall - a) * b + c; | ||||||||||
| // Ensure that min_luma doesn't become negative. | ||||||||||
| wd->csp.hdr.min_luma = MPMAX(wd->csp.hdr.min_luma, 0.0); | ||||||||||
| // Since we want to do some exact comparisons of max_luma with PL_COLOR_SDR_WHITE, | ||||||||||
|
|
@@ -2170,10 +2185,6 @@ static void info_done(void *data, struct wp_image_description_info_v1 *image_des | |||||||||
| wd->csp.hdr.max_fall = MPMIN(wd->csp.hdr.max_fall, wd->csp.hdr.max_luma); | ||||||||||
| } | ||||||||||
| wl->preferred_csp = wd->csp; | ||||||||||
| if (wd->csp.hdr.max_luma != PL_COLOR_SDR_WHITE && !pl_color_transfer_is_hdr(wd->csp.transfer)) { | ||||||||||
| MP_VERBOSE(wl, "Setting preferred transfer to PQ for HDR output.\n"); | ||||||||||
| wl->preferred_csp.transfer = PL_COLOR_TRC_PQ; | ||||||||||
| } | ||||||||||
| } else { | ||||||||||
| if (wl->icc_size) { | ||||||||||
| munmap(wl->icc_file, wl->icc_size); | ||||||||||
|
|
@@ -2351,6 +2362,10 @@ static void supported_coefficients_and_ranges(void *data, struct wp_color_repres | |||||||||
| wl->coefficients_map[PL_COLOR_SYSTEM_BT_2020_C] = WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_BT2020_CL; | ||||||||||
| wl->range_map[PL_COLOR_SYSTEM_BT_2020_C + offset] = range; | ||||||||||
| break; | ||||||||||
| case WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_ICTCP: | ||||||||||
| wl->coefficients_map[PL_COLOR_SYSTEM_BT_2100_PQ] = WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_ICTCP; | ||||||||||
| wl->range_map[PL_COLOR_SYSTEM_BT_2100_PQ + offset] = range; | ||||||||||
| break; | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
|
|
@@ -3513,6 +3528,48 @@ static void set_color_management(struct vo_wayland_state *wl, struct pl_color_sp | |||||||||
| wp_image_description_creator_params_v1_set_tf_named(image_creator_params, transfer); | ||||||||||
|
|
||||||||||
| struct pl_hdr_metadata hdr = color->hdr; | ||||||||||
|
|
||||||||||
| if (wl->supports_set_luminances) { | ||||||||||
| switch (color->transfer) { | ||||||||||
| case PL_COLOR_TRC_PQ: | ||||||||||
| // Set min luminance to 0 for PQ as per SMPTE ST 2084 | ||||||||||
| wp_image_description_creator_params_v1_set_luminances(image_creator_params, | ||||||||||
| 0 * WAYLAND_MIN_LUM_FACTOR, 10000, PL_COLOR_SDR_WHITE); | ||||||||||
| MP_VERBOSE(wl, "Setting PQ luminance range: min=0, max=10000, ref=%.2f\n", | ||||||||||
| PL_COLOR_SDR_WHITE); | ||||||||||
| // Mastering luminances will be set below | ||||||||||
| break; | ||||||||||
| case PL_COLOR_TRC_LINEAR: | ||||||||||
| // Our linear output is absolute scaled, meaning the 0 is absolute | ||||||||||
| // black, similar to PQ transfer. Configure it in the same way as PQ. | ||||||||||
| if (hdr.max_luma) { | ||||||||||
| wp_image_description_creator_params_v1_set_luminances(image_creator_params, | ||||||||||
| 0 * WAYLAND_MIN_LUM_FACTOR, hdr.max_luma, PL_COLOR_SDR_WHITE); | ||||||||||
| MP_VERBOSE(wl, "Setting linear luminance range: min=0, max=%.5f, ref=%.2f\n", | ||||||||||
| hdr.max_luma, PL_COLOR_SDR_WHITE); | ||||||||||
| if (hdr.min_luma && hdr.max_luma) { | ||||||||||
| wp_image_description_creator_params_v1_set_mastering_luminance(image_creator_params, | ||||||||||
| lrintf(hdr.min_luma * WAYLAND_MIN_LUM_FACTOR), lrintf(hdr.max_luma)); | ||||||||||
| MP_VERBOSE(wl, "Setting linear luminace mastering range: min=%.5f, max=%.2f\n", | ||||||||||
| hdr.min_luma, hdr.max_luma); | ||||||||||
| } | ||||||||||
| } | ||||||||||
| break; | ||||||||||
| case PL_COLOR_TRC_HLG: | ||||||||||
| // Leave default for HLG, we wouldn't output it directly, except for pass-through | ||||||||||
| break; | ||||||||||
| default: | ||||||||||
| // Set SDR luminance range for all relative transfers | ||||||||||
| if (hdr.min_luma && hdr.max_luma) { | ||||||||||
| wp_image_description_creator_params_v1_set_luminances(image_creator_params, | ||||||||||
| hdr.min_luma * WAYLAND_MIN_LUM_FACTOR, hdr.max_luma, PL_COLOR_SDR_WHITE); | ||||||||||
|
Comment on lines
+3564
to
+3565
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused about this (and similar with the linear case above). Shouldn't max=ref in this case?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it's configured correctly, it's will be max=ref. However, it can be configured differently, setting higher max works fine. |
||||||||||
| MP_VERBOSE(wl, "Setting relative luminance range: min=%.5f, max=%.2f, ref=%.2f\n", | ||||||||||
| hdr.min_luma, hdr.max_luma, PL_COLOR_SDR_WHITE); | ||||||||||
| } | ||||||||||
| break; | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| bool is_hdr = pl_color_transfer_is_hdr(color->transfer); | ||||||||||
| bool use_metadata = hdr_metadata_valid(wl, &hdr); | ||||||||||
| if (!use_metadata) | ||||||||||
|
|
@@ -3564,11 +3621,10 @@ static void set_color_representation(struct vo_wayland_state *wl, struct mp_imag | |||||||||
| if (!wl->color_representation_manager) | ||||||||||
| return; | ||||||||||
|
|
||||||||||
| if (wl->color_representation_surface) | ||||||||||
| if (wl->color_representation_surface) { | ||||||||||
| wp_color_representation_surface_v1_destroy(wl->color_representation_surface); | ||||||||||
|
|
||||||||||
| wl->color_representation_surface = | ||||||||||
| wp_color_representation_manager_v1_get_surface(wl->color_representation_manager, wl->callback_surface); | ||||||||||
| wl->color_representation_surface = NULL; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| int alpha = wl->alpha_map[params->repr.alpha]; | ||||||||||
| int coefficients = wl->coefficients_map[params->repr.sys]; | ||||||||||
|
|
@@ -3582,10 +3638,17 @@ static void set_color_representation(struct vo_wayland_state *wl, struct mp_imag | |||||||||
| MP_VERBOSE(wl, "Setting color representation:\n"); | ||||||||||
|
|
||||||||||
| if (coefficients && range) { | ||||||||||
| wl->color_representation_surface = | ||||||||||
| wp_color_representation_manager_v1_get_surface(wl->color_representation_manager, wl->callback_surface); | ||||||||||
|
Comment on lines
+3641
to
+3642
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe this is correct. There could be theoretical compositor that doesn't support the coefficient/range combination we want to set but does support the alpha/chromaloc. In such a case, we'll try to set them without a color repr surface
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I have it fixed locally, there was unrelated issue that caused problems. I will push later when I have time to work on this again. I got side-tracked again with luminances, because I'm still thinking if we should prefer PQ output and just output in gamma2.2 as compositors like to have it. |
||||||||||
| MP_VERBOSE(wl, " Coefficients: %s, Range: %s\n", | ||||||||||
| m_opt_choice_str(pl_csp_names, params->repr.sys), | ||||||||||
| m_opt_choice_str(pl_csp_levels_names, params->repr.levels)); | ||||||||||
| wp_color_representation_surface_v1_set_coefficients_and_range(wl->color_representation_surface, coefficients, range); | ||||||||||
| } else { | ||||||||||
| MP_WARN(wl, "Color representation %s / %s not supported! Output can be incorrect.\n", | ||||||||||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mahkoh: Why Jay doesn't advertise any coefficients as supported? I would expect any implementation that supports this protocol at least advertise the baseline, which it in fact supports. I'm not sure if that's intended, because it triggers this warning. I can exclude identity, because this in practice is always supported, but that seems weird.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Jay does not support any YCbCr formats.
I've implemented the protocol only for the alpha modes.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's fair. I think I will keep this warning, it may be weird thing to log when the output is fine. But this is the information we get. RGB/identity is not advertised as supported. Protocol states.
So, I assume that implementation should send RGB/identity as supported, if it is in fact supported. EDIT: Note to self, in case I forget, change it to
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But it doesn't support them. If you call set_coefficients_and_range at all, you will get a protocol error.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I kindly disagree that Jay doesn't support
That's why I don't call it to avoid protocol error and display warning.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW, I don't think we need to scare people with a warning here. Verbose is probably fine.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should warn, it would save us dozens of "wrong colors" issues that we get for dmabuf wayland. Note that it will warn only when color repr proto is actually supported, so it's quite valid thing to say that output will be wrong, if certain params are not supported.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Honestly my guess is that people would open an issue about the warning they see instead.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As they should, not for mpv probably, but their compositor.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The warning would only be visible with dmabuf-wayland in most cases, since full range rgb should be supported on |
||||||||||
| m_opt_choice_str(pl_csp_names, params->repr.sys), | ||||||||||
| m_opt_choice_str(pl_csp_levels_names, params->repr.levels)); | ||||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if (alpha) { | ||||||||||
|
|
@@ -4203,6 +4266,27 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg) | |||||||||
|
|
||||||||||
| void vo_wayland_handle_color(struct vo_wayland_state *wl, struct mp_image_params *params) | ||||||||||
| { | ||||||||||
| #if HAVE_WAYLAND_PROTOCOLS_1_41 | ||||||||||
| if (!params) { | ||||||||||
| if (wl->color_surface) { | ||||||||||
| wp_color_management_surface_v1_destroy(wl->color_surface); | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why have this destroy behavior? I guess that would mean hacks like
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea is when we set
Mesa supports Wayland nativelly now, so not only VK_hdr_layer is affected.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I forgot about the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, in all other cases, hint is defined to "something". Also we might at some point get rid of this option completely, but people still complain that "color is wrong", so restoring to dumb player mode is good to debug or just workaround other bugs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Well you will remove hdr support for us nvidia users, since amd have so many issues for me at the moment, I will be forced back to windows if this happens.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
this doesn't remove HDR support for nvidia. this PR makes it so that you dont need that layer for HDR support on nvidia There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Ah okay thanks, kind of traumatised by a certain other open source project's disregard for nvidia.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe this is sound as is. Consider the following code: static void image_description_failed(void *data, struct wp_image_description_v1 *image_description,
uint32_t cause, const char *msg)
{
struct vo_wayland_state *wl = data;
MP_VERBOSE(wl, "Image description failed: %d, %s\n", cause, msg);
wp_color_management_surface_v1_unset_image_description(wl->color_surface);
wp_image_description_v1_destroy(image_description);
}
// ...
struct wp_image_description_v1 *image_description = wp_image_description_creator_params_v1_create(image_creator_params);
wl_proxy_set_queue((struct wl_proxy *)image_description, wl->color_queue);
wp_image_description_v1_add_listener(image_description, &image_description_listener, wl);If the color_surface is destroyed while the image description is pending, the callback will access a NULL pointer. Furthermore, it is probably a good idea to store the image_description inside
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe that is necessarily the case. See the discussion in #17495. |
||||||||||
| wl->color_surface = NULL; | ||||||||||
| } | ||||||||||
| if (wl->color_queue) { | ||||||||||
| wl_event_queue_destroy(wl->color_queue); | ||||||||||
| wl->color_queue = NULL; | ||||||||||
| } | ||||||||||
|
Comment on lines
+4275
to
+4278
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think it's fine to keep the queue alive.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, will do. |
||||||||||
| wl->current_params = (struct mp_image_params){0}; | ||||||||||
| return; | ||||||||||
| } | ||||||||||
| if (wl->color_manager) { | ||||||||||
| if (!wl->color_queue) | ||||||||||
| wl->color_queue = wl_display_create_queue_with_name(wl->display, "image description creator queue"); | ||||||||||
| if (!wl->color_surface) | ||||||||||
| wl->color_surface = wp_color_manager_v1_get_surface(wl->color_manager, wl->callback_surface); | ||||||||||
| } | ||||||||||
| #endif | ||||||||||
|
|
||||||||||
| bool color_space_changed = !pl_color_space_equal(&wl->current_params.color, ¶ms->color); | ||||||||||
| bool color_repr_changed = !pl_color_repr_equal(&wl->current_params.repr, ¶ms->repr) || | ||||||||||
| wl->current_params.chroma_location != params->chroma_location; | ||||||||||
|
|
@@ -4335,11 +4419,6 @@ bool vo_wayland_init(struct vo *vo) | |||||||||
| if (wl->color_manager) { | ||||||||||
| wl->color_surface_feedback = wp_color_manager_v1_get_surface_feedback(wl->color_manager, wl->callback_surface); | ||||||||||
| wp_color_management_surface_feedback_v1_add_listener(wl->color_surface_feedback, &surface_feedback_listener, wl); | ||||||||||
| // Only bind color surface to vo_dmabuf_wayland for now to avoid conflicting with graphics drivers | ||||||||||
| if (!strcmp(wl->vo->driver->name, "dmabuf-wayland")) { | ||||||||||
| wl->color_surface = wp_color_manager_v1_get_surface(wl->color_manager, wl->callback_surface); | ||||||||||
| wl->color_queue = wl_display_create_queue_with_name(wl->display, "image description creator queue"); | ||||||||||
| } | ||||||||||
| } else { | ||||||||||
| MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", | ||||||||||
| wp_color_manager_v1_interface.name); | ||||||||||
|
|
||||||||||
Uh oh!
There was an error while loading. Please reload this page.