diff --git a/meson.build b/meson.build index d4e69ba8a296a9f2febc3b19bc81fcd82062f031..3c1e5f9ac4be322b97081bb697c74c5937615609 100644 --- a/meson.build +++ b/meson.build @@ -2,7 +2,7 @@ project('libplacebo', ['c', 'cpp'], license: 'LGPL2.1+', default_options: ['c_std=c99', 'cpp_std=c++11', 'warning_level=2'], meson_version: '>=0.49', - version: '2.66.0', + version: '2.67.0', ) # Version number diff --git a/src/colorspace.c b/src/colorspace.c index 2cd6b4808a247812056f488204d09779b96c8695..a605d67f4cc9808c04da0e9eea540c7d0c261d91 100644 --- a/src/colorspace.c +++ b/src/colorspace.c @@ -371,6 +371,9 @@ void pl_chroma_location_offset(enum pl_chroma_location loc, float *x, float *y) { *x = *y = 0; + // This is the majority of subsampled chroma content out there + loc = PL_DEF(loc, PL_CHROMA_TOP_LEFT); + switch (loc) { case PL_CHROMA_LEFT: case PL_CHROMA_TOP_LEFT: diff --git a/src/include/libplacebo/colorspace.h b/src/include/libplacebo/colorspace.h index 6d8d0420c7192ed4660c7509d7448c9200707c65..4713993505becd1c9aa0a7d137b68ea1d6dc6fbf 100644 --- a/src/include/libplacebo/colorspace.h +++ b/src/include/libplacebo/colorspace.h @@ -342,6 +342,8 @@ enum pl_chroma_location { // Fills *x and *y with the offset in luma pixels corresponding to a given // chroma location. +// +// Note: PL_CHROMA_UNKNOWN defaults to PL_CHROMA_TOP_LEFT void pl_chroma_location_offset(enum pl_chroma_location loc, float *x, float *y); // Represents a single CIE xy coordinate (e.g. CIE Yxy with Y = 1.0) diff --git a/src/include/libplacebo/renderer.h b/src/include/libplacebo/renderer.h index b3ccf57ba3c69197b7629338c1b060d19b630e8b..7ecf98e310d56f4802ae2b6d46e2582808366bbc 100644 --- a/src/include/libplacebo/renderer.h +++ b/src/include/libplacebo/renderer.h @@ -376,6 +376,12 @@ struct pl_image { int width, height; }; +// Helper function to infer the chroma location offset for each plane in an +// image. This is equivalent to calling `pl_chroma_location_offset` on all +// subsampled planes' shift_x/shift_y variables. +void pl_image_set_chroma_location(struct pl_image *image, + enum pl_chroma_location chroma_loc); + // Represents the target of a rendering operation struct pl_render_target { // The framebuffer (or texture) we want to render to. Must have `renderable` diff --git a/src/renderer.c b/src/renderer.c index 8ec09569bccac7fab8fcb71dd68c2ea09967ff3f..ffa99334822eb8796389762c60faa3e0d7b8f0de 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -1681,6 +1681,48 @@ error: return false; } +void pl_image_set_chroma_location(struct pl_image *image, + enum pl_chroma_location chroma_loc) +{ + // Re-use our internal helpers for this + struct plane_state planes[4]; + struct plane_state *ref = NULL; + + pl_assert(image->num_planes < PL_ARRAY_SIZE(planes)); + for (int i = 0; i < image->num_planes; i++) { + struct plane_state *st = &planes[i]; + *st = (struct plane_state) { + .plane = image->planes[i], + .img = { .repr = image->repr, }, + }; + + st->type = detect_plane_type(st); + pl_assert(st->type >= 0); + switch (st->type) { + case PLANE_RGB: + case PLANE_LUMA: + case PLANE_XYZ: + ref = st; + break; + default: break; + } + } + + if (!ref) + return; // no planes + + int ref_w = ref->plane.texture->params.w, + ref_h = ref->plane.texture->params.h; + + for (int i = 0; i < image->num_planes; i++) { + struct pl_plane *plane = &image->planes[i]; + const struct pl_tex *tex = plane->texture; + bool subsampled = tex->params.w < ref_w || tex->params.h < ref_h; + if (subsampled) + pl_chroma_location_offset(chroma_loc, &plane->shift_x, &plane->shift_y); + } +} + void pl_render_target_from_swapchain(struct pl_render_target *out_target, const struct pl_swapchain_frame *frame) {