@@ -2146,10 +2146,22 @@ static void info_done(void *data, struct wp_image_description_info_v1 *image_des
21462146 struct vo_wayland_state * wl = wd -> wl ;
21472147 wp_image_description_info_v1_destroy (image_description_info );
21482148 if (!wd -> icc_file ) {
2149- wl -> preferred_csp = wd -> csp ;
21502149 MP_VERBOSE (wl , "Preferred surface feedback received:\n" );
21512150 log_color_space (wl -> log , wd );
2152- if (wd -> csp .hdr .max_luma > wd -> ref_luma ) {
2151+ // Wayland luminances are always in reference to the reference luminance. That is,
2152+ // if max_luma == 2*ref_luma, then there is 2x headroom above paper white. On the
2153+ // other hand, libplacebo hardcodes PL_COLOR_SDR_WHITE as the reference luminance.
2154+ // We must scale all wayland values to correspond to the libplacebo scale,
2155+ // otherwise libplacebo will assume that there is too little or too much headroom
2156+ // when ref_luma != PL_COLOR_SDR_WHITE.
2157+ float a = wd -> min_luma ;
2158+ float b = (PL_COLOR_SDR_WHITE - a ) / (wd -> ref_luma - a );
2159+ wd -> csp .hdr .min_luma = (wd -> csp .hdr .min_luma - a ) * b + a ;
2160+ wd -> csp .hdr .max_luma = (wd -> csp .hdr .max_luma - a ) * b + a ;
2161+ wd -> csp .hdr .max_cll = (wd -> csp .hdr .max_cll - a ) * b + a ;
2162+ wd -> csp .hdr .max_fall = (wd -> csp .hdr .max_fall - a ) * b + a ;
2163+ wl -> preferred_csp = wd -> csp ;
2164+ if (wd -> csp .hdr .max_luma > PL_COLOR_SDR_WHITE ) {
21532165 MP_VERBOSE (wl , "Setting preferred transfer to PQ for HDR output.\n" );
21542166 wl -> preferred_csp .transfer = PL_COLOR_TRC_PQ ;
21552167 }
0 commit comments