summaryrefslogtreecommitdiffstats
path: root/video/out/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/gpu')
-rw-r--r--video/out/gpu/context.c11
-rw-r--r--video/out/gpu/context.h2
-rw-r--r--video/out/gpu/d3d11_helpers.c129
-rw-r--r--video/out/gpu/d3d11_helpers.h19
-rw-r--r--video/out/gpu/error_diffusion.c3
-rw-r--r--video/out/gpu/hwdec.c4
-rw-r--r--video/out/gpu/hwdec.h8
-rw-r--r--video/out/gpu/lcms.c62
-rw-r--r--video/out/gpu/lcms.h6
-rw-r--r--video/out/gpu/libmpv_gpu.c2
-rw-r--r--video/out/gpu/osd.c4
-rw-r--r--video/out/gpu/osd.h2
-rw-r--r--video/out/gpu/ra.h4
-rw-r--r--video/out/gpu/spirv.c1
-rw-r--r--video/out/gpu/user_shaders.c4
-rw-r--r--video/out/gpu/user_shaders.h2
-rw-r--r--video/out/gpu/utils.c6
-rw-r--r--video/out/gpu/utils.h2
-rw-r--r--video/out/gpu/video.c358
-rw-r--r--video/out/gpu/video.h17
-rw-r--r--video/out/gpu/video_shaders.c128
-rw-r--r--video/out/gpu/video_shaders.h9
22 files changed, 426 insertions, 357 deletions
diff --git a/video/out/gpu/context.c b/video/out/gpu/context.c
index 5ce18af..88d4f42 100644
--- a/video/out/gpu/context.c
+++ b/video/out/gpu/context.c
@@ -41,7 +41,6 @@ extern const struct ra_ctx_fns ra_ctx_wayland_egl;
extern const struct ra_ctx_fns ra_ctx_wgl;
extern const struct ra_ctx_fns ra_ctx_angle;
extern const struct ra_ctx_fns ra_ctx_dxgl;
-extern const struct ra_ctx_fns ra_ctx_rpi;
extern const struct ra_ctx_fns ra_ctx_android;
/* Vulkan */
@@ -67,9 +66,6 @@ static const struct ra_ctx_fns *contexts[] = {
#if HAVE_EGL_ANDROID
&ra_ctx_android,
#endif
-#if HAVE_RPI
- &ra_ctx_rpi,
-#endif
#if HAVE_EGL_ANGLE_WIN32
&ra_ctx_angle,
#endif
@@ -133,8 +129,7 @@ static int ra_ctx_api_help(struct mp_log *log, const struct m_option *opt,
return M_OPT_EXIT;
}
-static int ra_ctx_validate_api(struct mp_log *log, const struct m_option *opt,
- struct bstr name, const char **value)
+static inline OPT_STRING_VALIDATE_FUNC(ra_ctx_validate_api)
{
struct bstr param = bstr0(*value);
if (bstr_equals0(param, "auto"))
@@ -158,8 +153,7 @@ static int ra_ctx_context_help(struct mp_log *log, const struct m_option *opt,
return M_OPT_EXIT;
}
-static int ra_ctx_validate_context(struct mp_log *log, const struct m_option *opt,
- struct bstr name, const char **value)
+static inline OPT_STRING_VALIDATE_FUNC(ra_ctx_validate_context)
{
struct bstr param = bstr0(*value);
if (bstr_equals0(param, "auto"))
@@ -208,6 +202,7 @@ struct ra_ctx *ra_ctx_create(struct vo *vo, struct ra_ctx_opts opts)
MP_VERBOSE(ctx, "Initializing GPU context '%s'\n", ctx->fns->name);
if (contexts[i]->init(ctx)) {
vo->probing = old_probing;
+ vo->context_name = ctx->fns->name;
return ctx;
}
diff --git a/video/out/gpu/context.h b/video/out/gpu/context.h
index 6788e6f..447f40b 100644
--- a/video/out/gpu/context.h
+++ b/video/out/gpu/context.h
@@ -72,7 +72,7 @@ struct ra_fbo {
// Host system's colorspace that it will be interpreting
// the frame buffer as.
- struct mp_colorspace color_space;
+ struct pl_color_space color_space;
};
struct ra_swapchain_fns {
diff --git a/video/out/gpu/d3d11_helpers.c b/video/out/gpu/d3d11_helpers.c
index 30d9eae..d45c038 100644
--- a/video/out/gpu/d3d11_helpers.c
+++ b/video/out/gpu/d3d11_helpers.c
@@ -228,9 +228,9 @@ static const char *d3d11_get_csp_name(DXGI_COLOR_SPACE_TYPE csp)
}
static bool d3d11_get_mp_csp(DXGI_COLOR_SPACE_TYPE csp,
- struct mp_colorspace *mp_csp)
+ struct pl_color_space *pl_color_system)
{
- if (!mp_csp)
+ if (!pl_color_system)
return false;
// Colorspaces utilizing gamma 2.2 (G22) are set to
@@ -243,27 +243,27 @@ static bool d3d11_get_mp_csp(DXGI_COLOR_SPACE_TYPE csp,
// regarding not doing conversion from BT.601 to BT.709.
switch (csp) {
case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709:
- *mp_csp = (struct mp_colorspace){
- .gamma = MP_CSP_TRC_AUTO,
- .primaries = MP_CSP_PRIM_AUTO,
+ *pl_color_system = (struct pl_color_space){
+ .transfer = PL_COLOR_TRC_UNKNOWN,
+ .primaries = PL_COLOR_PRIM_UNKNOWN,
};
break;
case DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709:
- *mp_csp = (struct mp_colorspace) {
- .gamma = MP_CSP_TRC_LINEAR,
- .primaries = MP_CSP_PRIM_AUTO,
+ *pl_color_system = (struct pl_color_space) {
+ .transfer = PL_COLOR_TRC_LINEAR,
+ .primaries = PL_COLOR_PRIM_UNKNOWN,
};
break;
case DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020:
- *mp_csp = (struct mp_colorspace) {
- .gamma = MP_CSP_TRC_PQ,
- .primaries = MP_CSP_PRIM_BT_2020,
+ *pl_color_system = (struct pl_color_space) {
+ .transfer = PL_COLOR_TRC_PQ,
+ .primaries = PL_COLOR_PRIM_BT_2020,
};
break;
case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020:
- *mp_csp = (struct mp_colorspace) {
- .gamma = MP_CSP_TRC_AUTO,
- .primaries = MP_CSP_PRIM_BT_2020,
+ *pl_color_system = (struct pl_color_space) {
+ .transfer = PL_COLOR_TRC_UNKNOWN,
+ .primaries = PL_COLOR_PRIM_BT_2020,
};
break;
default:
@@ -287,28 +287,8 @@ static bool query_output_format_and_colorspace(struct mp_log *log,
if (!out_fmt || !out_cspace)
return false;
- HRESULT hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
- if (FAILED(hr)) {
- mp_err(log, "Failed to get swap chain's containing output: %s!\n",
- mp_HRESULT_to_str(hr));
- goto done;
- }
-
- hr = IDXGIOutput_QueryInterface(output, &IID_IDXGIOutput6,
- (void**)&output6);
- if (FAILED(hr)) {
- // point where systems older than Windows 10 would fail,
- // thus utilizing error log level only with windows 10+
- mp_msg(log, IsWindows10OrGreater() ? MSGL_ERR : MSGL_V,
- "Failed to create a DXGI 1.6 output interface: %s\n",
- mp_HRESULT_to_str(hr));
- goto done;
- }
-
- hr = IDXGIOutput6_GetDesc1(output6, &desc);
- if (FAILED(hr)) {
- mp_err(log, "Failed to query swap chain's output information: %s\n",
- mp_HRESULT_to_str(hr));
+ if (!mp_get_dxgi_output_desc(swapchain, &desc)) {
+ mp_err(log, "Failed to query swap chain's output information\n");
goto done;
}
@@ -371,9 +351,9 @@ static int get_feature_levels(int max_fl, int min_fl,
return len;
}
-static IDXGIAdapter1 *get_d3d11_adapter(struct mp_log *log,
- struct bstr requested_adapter_name,
- struct bstr *listing)
+IDXGIAdapter1 *mp_get_dxgi_adapter(struct mp_log *log,
+ bstr requested_adapter_name,
+ bstr *listing)
{
HRESULT hr = S_OK;
IDXGIFactory1 *factory;
@@ -437,6 +417,37 @@ static IDXGIAdapter1 *get_d3d11_adapter(struct mp_log *log,
return picked_adapter;
}
+int mp_dxgi_validate_adapter(struct mp_log *log,
+ const struct m_option *opt,
+ struct bstr name, const char **value)
+{
+ struct bstr param = bstr0(*value);
+ bool help = bstr_equals0(param, "help");
+ bool adapter_matched = false;
+ struct bstr listing = { 0 };
+
+ if (bstr_equals0(param, "")) {
+ return 0;
+ }
+
+ adapter_matched = mp_dxgi_list_or_verify_adapters(log,
+ help ? bstr0(NULL) : param,
+ help ? &listing : NULL);
+
+ if (help) {
+ mp_info(log, "Available DXGI adapters:\n%.*s",
+ BSTR_P(listing));
+ talloc_free(listing.start);
+ return M_OPT_EXIT;
+ }
+
+ if (!adapter_matched) {
+ mp_err(log, "No adapter matching '%.*s'!\n", BSTR_P(param));
+ }
+
+ return adapter_matched ? 0 : M_OPT_INVALID;
+}
+
static HRESULT create_device(struct mp_log *log, IDXGIAdapter1 *adapter,
bool warp, bool debug, int max_fl, int min_fl,
ID3D11Device **dev)
@@ -455,9 +466,9 @@ static HRESULT create_device(struct mp_log *log, IDXGIAdapter1 *adapter,
NULL, flags, levels, levels_len, D3D11_SDK_VERSION, dev, NULL, NULL);
}
-bool mp_d3d11_list_or_verify_adapters(struct mp_log *log,
- bstr adapter_name,
- bstr *listing)
+bool mp_dxgi_list_or_verify_adapters(struct mp_log *log,
+ bstr adapter_name,
+ bstr *listing)
{
IDXGIAdapter1 *picked_adapter = NULL;
@@ -465,7 +476,7 @@ bool mp_d3d11_list_or_verify_adapters(struct mp_log *log,
return false;
}
- if ((picked_adapter = get_d3d11_adapter(log, adapter_name, listing))) {
+ if ((picked_adapter = mp_get_dxgi_adapter(log, adapter_name, listing))) {
SAFE_RELEASE(picked_adapter);
return true;
}
@@ -497,7 +508,7 @@ bool mp_d3d11_create_present_device(struct mp_log *log,
goto done;
}
- adapter = get_d3d11_adapter(log, bstr0(adapter_name), NULL);
+ adapter = mp_get_dxgi_adapter(log, bstr0(adapter_name), NULL);
if (adapter_name && !adapter) {
mp_warn(log, "Adapter matching '%s' was not found in the system! "
@@ -793,7 +804,7 @@ static bool configure_created_swapchain(struct mp_log *log,
IDXGISwapChain *swapchain,
DXGI_FORMAT requested_format,
DXGI_COLOR_SPACE_TYPE requested_csp,
- struct mp_colorspace *configured_csp)
+ struct pl_color_space *configured_csp)
{
DXGI_FORMAT probed_format = DXGI_FORMAT_UNKNOWN;
DXGI_FORMAT selected_format = DXGI_FORMAT_UNKNOWN;
@@ -801,7 +812,7 @@ static bool configure_created_swapchain(struct mp_log *log,
DXGI_COLOR_SPACE_TYPE selected_colorspace;
const char *format_name = NULL;
const char *csp_name = NULL;
- struct mp_colorspace mp_csp = { 0 };
+ struct pl_color_space pl_color_system = { 0 };
bool mp_csp_mapped = false;
query_output_format_and_colorspace(log, swapchain,
@@ -817,7 +828,7 @@ static bool configure_created_swapchain(struct mp_log *log,
requested_csp : probed_colorspace;
format_name = d3d11_get_format_name(selected_format);
csp_name = d3d11_get_csp_name(selected_colorspace);
- mp_csp_mapped = d3d11_get_mp_csp(selected_colorspace, &mp_csp);
+ mp_csp_mapped = d3d11_get_mp_csp(selected_colorspace, &pl_color_system);
mp_verbose(log, "Selected swapchain format %s (%d), attempting "
"to utilize it.\n",
@@ -848,7 +859,7 @@ static bool configure_created_swapchain(struct mp_log *log,
"mapping! Overriding to standard sRGB!\n",
csp_name, selected_colorspace);
selected_colorspace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
- d3d11_get_mp_csp(selected_colorspace, &mp_csp);
+ d3d11_get_mp_csp(selected_colorspace, &pl_color_system);
}
mp_verbose(log, "Selected swapchain color space %s (%d), attempting to "
@@ -860,7 +871,7 @@ static bool configure_created_swapchain(struct mp_log *log,
}
if (configured_csp) {
- *configured_csp = mp_csp;
+ *configured_csp = pl_color_system;
}
return true;
@@ -964,3 +975,23 @@ done:
SAFE_RELEASE(dxgi_dev);
return success;
}
+
+bool mp_get_dxgi_output_desc(IDXGISwapChain *swapchain, DXGI_OUTPUT_DESC1 *desc)
+{
+ bool ret = false;
+ IDXGIOutput *output = NULL;
+ IDXGIOutput6 *output6 = NULL;
+
+ if (FAILED(IDXGISwapChain_GetContainingOutput(swapchain, &output)))
+ goto done;
+
+ if (FAILED(IDXGIOutput_QueryInterface(output, &IID_IDXGIOutput6, (void**)&output6)))
+ goto done;
+
+ ret = SUCCEEDED(IDXGIOutput6_GetDesc1(output6, desc));
+
+done:
+ SAFE_RELEASE(output);
+ SAFE_RELEASE(output6);
+ return ret;
+}
diff --git a/video/out/gpu/d3d11_helpers.h b/video/out/gpu/d3d11_helpers.h
index c115d33..6cc6818 100644
--- a/video/out/gpu/d3d11_helpers.h
+++ b/video/out/gpu/d3d11_helpers.h
@@ -22,6 +22,7 @@
#include <windows.h>
#include <d3d11.h>
#include <dxgi1_2.h>
+#include <dxgi1_6.h>
#include "video/mp_image.h"
@@ -65,9 +66,17 @@ struct d3d11_device_opts {
char *adapter_name;
};
-bool mp_d3d11_list_or_verify_adapters(struct mp_log *log,
- bstr adapter_name,
- bstr *listing);
+IDXGIAdapter1 *mp_get_dxgi_adapter(struct mp_log *log,
+ bstr requested_adapter_name,
+ bstr *listing);
+
+bool mp_get_dxgi_output_desc(IDXGISwapChain *swapchain, DXGI_OUTPUT_DESC1 *desc);
+
+OPT_STRING_VALIDATE_FUNC(mp_dxgi_validate_adapter);
+
+bool mp_dxgi_list_or_verify_adapters(struct mp_log *log,
+ bstr adapter_name,
+ bstr *listing);
bool mp_d3d11_create_present_device(struct mp_log *log,
struct d3d11_device_opts *opts,
@@ -80,10 +89,10 @@ struct d3d11_swapchain_opts {
DXGI_FORMAT format;
DXGI_COLOR_SPACE_TYPE color_space;
- // mp_colorspace mapping of the configured swapchain colorspace
+ // pl_color_space mapping of the configured swapchain colorspace
// shall be written into this memory location if configuration
// succeeds. Will be ignored if NULL.
- struct mp_colorspace *configured_csp;
+ struct pl_color_space *configured_csp;
// Use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL if possible
bool flip;
diff --git a/video/out/gpu/error_diffusion.c b/video/out/gpu/error_diffusion.c
index c1ea542..72063c3 100644
--- a/video/out/gpu/error_diffusion.c
+++ b/video/out/gpu/error_diffusion.c
@@ -227,7 +227,8 @@ void pass_error_diffusion(struct gl_shader_cache *sc,
}
// Different kernels for error diffusion.
-// Patterns are from http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT
+// Patterns are from <https://web.archive.org/web/20181031005427/
+// http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT>
const struct error_diffusion_kernel mp_error_diffusion_kernels[] = {
{
.name = "simple",
diff --git a/video/out/gpu/hwdec.c b/video/out/gpu/hwdec.c
index c8098f3..c7d817c 100644
--- a/video/out/gpu/hwdec.c
+++ b/video/out/gpu/hwdec.c
@@ -34,7 +34,6 @@ extern const struct ra_hwdec_driver ra_hwdec_dxva2gldx;
extern const struct ra_hwdec_driver ra_hwdec_d3d11va;
extern const struct ra_hwdec_driver ra_hwdec_dxva2dxgi;
extern const struct ra_hwdec_driver ra_hwdec_cuda;
-extern const struct ra_hwdec_driver ra_hwdec_rpi_overlay;
extern const struct ra_hwdec_driver ra_hwdec_drmprime;
extern const struct ra_hwdec_driver ra_hwdec_drmprime_overlay;
extern const struct ra_hwdec_driver ra_hwdec_aimagereader;
@@ -70,9 +69,6 @@ const struct ra_hwdec_driver *const ra_hwdec_drivers[] = {
#if HAVE_VDPAU_GL_X11
&ra_hwdec_vdpau,
#endif
-#if HAVE_RPI_MMAL
- &ra_hwdec_rpi_overlay,
-#endif
#if HAVE_DRM
&ra_hwdec_drmprime,
&ra_hwdec_drmprime_overlay,
diff --git a/video/out/gpu/hwdec.h b/video/out/gpu/hwdec.h
index 7766073..f195606 100644
--- a/video/out/gpu/hwdec.h
+++ b/video/out/gpu/hwdec.h
@@ -18,12 +18,8 @@ struct ra_hwdec_ctx {
int num_hwdecs;
};
-int ra_hwdec_validate_opt(struct mp_log *log, const m_option_t *opt,
- struct bstr name, const char **value);
-
-int ra_hwdec_validate_drivers_only_opt(struct mp_log *log,
- const m_option_t *opt,
- struct bstr name, const char **value);
+OPT_STRING_VALIDATE_FUNC(ra_hwdec_validate_opt);
+OPT_STRING_VALIDATE_FUNC(ra_hwdec_validate_drivers_only_opt);
void ra_hwdec_ctx_init(struct ra_hwdec_ctx *ctx, struct mp_hwdec_devices *devs,
const char *opt, bool load_all_by_default);
diff --git a/video/out/gpu/lcms.c b/video/out/gpu/lcms.c
index 7006a96..c197acf 100644
--- a/video/out/gpu/lcms.c
+++ b/video/out/gpu/lcms.c
@@ -46,8 +46,8 @@ struct gl_lcms {
char *current_profile;
bool using_memory_profile;
bool changed;
- enum mp_csp_prim current_prim;
- enum mp_csp_trc current_trc;
+ enum pl_color_primaries current_prim;
+ enum pl_color_transfer current_trc;
struct mp_log *log;
struct mpv_global *global;
@@ -162,8 +162,8 @@ static bool vid_profile_eq(struct AVBufferRef *a, struct AVBufferRef *b)
// Return whether the profile or config has changed since the last time it was
// retrieved. If it has changed, gl_lcms_get_lut3d() should be called.
-bool gl_lcms_has_changed(struct gl_lcms *p, enum mp_csp_prim prim,
- enum mp_csp_trc trc, struct AVBufferRef *vid_profile)
+bool gl_lcms_has_changed(struct gl_lcms *p, enum pl_color_primaries prim,
+ enum pl_color_transfer trc, struct AVBufferRef *vid_profile)
{
if (p->changed || p->current_prim != prim || p->current_trc != trc)
return true;
@@ -180,7 +180,7 @@ bool gl_lcms_has_profile(struct gl_lcms *p)
static cmsHPROFILE get_vid_profile(struct gl_lcms *p, cmsContext cms,
cmsHPROFILE disp_profile,
- enum mp_csp_prim prim, enum mp_csp_trc trc)
+ enum pl_color_primaries prim, enum pl_color_transfer trc)
{
if (p->opts->use_embedded && p->vid_profile) {
// Try using the embedded ICC profile
@@ -197,36 +197,41 @@ static cmsHPROFILE get_vid_profile(struct gl_lcms *p, cmsContext cms,
// The input profile for the transformation is dependent on the video
// primaries and transfer characteristics
- struct mp_csp_primaries csp = mp_get_csp_primaries(prim);
- cmsCIExyY wp_xyY = {csp.white.x, csp.white.y, 1.0};
+ const struct pl_raw_primaries *csp = pl_raw_primaries_get(prim);
+ cmsCIExyY wp_xyY = {csp->white.x, csp->white.y, 1.0};
cmsCIExyYTRIPLE prim_xyY = {
- .Red = {csp.red.x, csp.red.y, 1.0},
- .Green = {csp.green.x, csp.green.y, 1.0},
- .Blue = {csp.blue.x, csp.blue.y, 1.0},
+ .Red = {csp->red.x, csp->red.y, 1.0},
+ .Green = {csp->green.x, csp->green.y, 1.0},
+ .Blue = {csp->blue.x, csp->blue.y, 1.0},
};
cmsToneCurve *tonecurve[3] = {0};
switch (trc) {
- case MP_CSP_TRC_LINEAR: tonecurve[0] = cmsBuildGamma(cms, 1.0); break;
- case MP_CSP_TRC_GAMMA18: tonecurve[0] = cmsBuildGamma(cms, 1.8); break;
- case MP_CSP_TRC_GAMMA20: tonecurve[0] = cmsBuildGamma(cms, 2.0); break;
- case MP_CSP_TRC_GAMMA22: tonecurve[0] = cmsBuildGamma(cms, 2.2); break;
- case MP_CSP_TRC_GAMMA24: tonecurve[0] = cmsBuildGamma(cms, 2.4); break;
- case MP_CSP_TRC_GAMMA26: tonecurve[0] = cmsBuildGamma(cms, 2.6); break;
- case MP_CSP_TRC_GAMMA28: tonecurve[0] = cmsBuildGamma(cms, 2.8); break;
-
- case MP_CSP_TRC_SRGB:
+ case PL_COLOR_TRC_LINEAR: tonecurve[0] = cmsBuildGamma(cms, 1.0); break;
+ case PL_COLOR_TRC_GAMMA18: tonecurve[0] = cmsBuildGamma(cms, 1.8); break;
+ case PL_COLOR_TRC_GAMMA20: tonecurve[0] = cmsBuildGamma(cms, 2.0); break;
+ case PL_COLOR_TRC_GAMMA22: tonecurve[0] = cmsBuildGamma(cms, 2.2); break;
+ case PL_COLOR_TRC_GAMMA24: tonecurve[0] = cmsBuildGamma(cms, 2.4); break;
+ case PL_COLOR_TRC_GAMMA26: tonecurve[0] = cmsBuildGamma(cms, 2.6); break;
+ case PL_COLOR_TRC_GAMMA28: tonecurve[0] = cmsBuildGamma(cms, 2.8); break;
+
+ case PL_COLOR_TRC_ST428:
+ tonecurve[0] = cmsBuildParametricToneCurve(cms, 2,
+ (double[3]){2.6, pow(52.37/48.0, 1/2.6), 0.0});
+ break;
+
+ case PL_COLOR_TRC_SRGB:
// Values copied from Little-CMS
tonecurve[0] = cmsBuildParametricToneCurve(cms, 4,
(double[5]){2.40, 1/1.055, 0.055/1.055, 1/12.92, 0.04045});
break;
- case MP_CSP_TRC_PRO_PHOTO:
+ case PL_COLOR_TRC_PRO_PHOTO:
tonecurve[0] = cmsBuildParametricToneCurve(cms, 4,
(double[5]){1.8, 1.0, 0.0, 1/16.0, 0.03125});
break;
- case MP_CSP_TRC_BT_1886: {
+ case PL_COLOR_TRC_BT_1886: {
double src_black[3];
if (p->opts->contrast < 0) {
// User requested infinite contrast, return 2.4 profile
@@ -242,7 +247,7 @@ static cmsHPROFILE get_vid_profile(struct gl_lcms *p, cmsContext cms,
// function. Relative colorimetric is used since we want to
// approximate the BT.1886 to the target device's actual black
// point even in e.g. perceptual mode
- const int intent = MP_INTENT_RELATIVE_COLORIMETRIC;
+ const int intent = PL_INTENT_RELATIVE_COLORIMETRIC;
cmsCIEXYZ bp_XYZ;
if (!cmsDetectBlackPoint(&bp_XYZ, disp_profile, intent, 0))
return false;
@@ -300,7 +305,7 @@ static cmsHPROFILE get_vid_profile(struct gl_lcms *p, cmsContext cms,
}
bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **result_lut3d,
- enum mp_csp_prim prim, enum mp_csp_trc trc,
+ enum pl_color_primaries prim, enum pl_color_transfer trc,
struct AVBufferRef *vid_profile)
{
int s_r, s_g, s_b;
@@ -474,8 +479,8 @@ struct gl_lcms *gl_lcms_init(void *talloc_ctx, struct mp_log *log,
void gl_lcms_update_options(struct gl_lcms *p) { }
bool gl_lcms_set_memory_profile(struct gl_lcms *p, bstr profile) {return false;}
-bool gl_lcms_has_changed(struct gl_lcms *p, enum mp_csp_prim prim,
- enum mp_csp_trc trc, struct AVBufferRef *vid_profile)
+bool gl_lcms_has_changed(struct gl_lcms *p, enum pl_color_primaries prim,
+ enum pl_color_transfer trc, struct AVBufferRef *vid_profile)
{
return false;
}
@@ -486,7 +491,7 @@ bool gl_lcms_has_profile(struct gl_lcms *p)
}
bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **result_lut3d,
- enum mp_csp_prim prim, enum mp_csp_trc trc,
+ enum pl_color_primaries prim, enum pl_color_transfer trc,
struct AVBufferRef *vid_profile)
{
return false;
@@ -494,8 +499,7 @@ bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **result_lut3d,
#endif
-static int validate_3dlut_size_opt(struct mp_log *log, const m_option_t *opt,
- struct bstr name, const char **value)
+static inline OPT_STRING_VALIDATE_FUNC(validate_3dlut_size_opt)
{
int p1, p2, p3;
return gl_parse_3dlut_size(*value, &p1, &p2, &p3) ? 0 : M_OPT_INVALID;
@@ -519,7 +523,7 @@ const struct m_sub_options mp_icc_conf = {
.size = sizeof(struct mp_icc_opts),
.defaults = &(const struct mp_icc_opts) {
.size_str = "auto",
- .intent = MP_INTENT_RELATIVE_COLORIMETRIC,
+ .intent = PL_INTENT_RELATIVE_COLORIMETRIC,
.use_embedded = true,
.cache = true,
},
diff --git a/video/out/gpu/lcms.h b/video/out/gpu/lcms.h
index 607353a..d0b0fe5 100644
--- a/video/out/gpu/lcms.h
+++ b/video/out/gpu/lcms.h
@@ -37,10 +37,10 @@ void gl_lcms_update_options(struct gl_lcms *p);
bool gl_lcms_set_memory_profile(struct gl_lcms *p, bstr profile);
bool gl_lcms_has_profile(struct gl_lcms *p);
bool gl_lcms_get_lut3d(struct gl_lcms *p, struct lut3d **,
- enum mp_csp_prim prim, enum mp_csp_trc trc,
+ enum pl_color_primaries prim, enum pl_color_transfer trc,
struct AVBufferRef *vid_profile);
-bool gl_lcms_has_changed(struct gl_lcms *p, enum mp_csp_prim prim,
- enum mp_csp_trc trc, struct AVBufferRef *vid_profile);
+bool gl_lcms_has_changed(struct gl_lcms *p, enum pl_color_primaries prim,
+ enum pl_color_transfer trc, struct AVBufferRef *vid_profile);
static inline bool gl_parse_3dlut_size(const char *arg, int *p1, int *p2, int *p3)
{
diff --git a/video/out/gpu/libmpv_gpu.c b/video/out/gpu/libmpv_gpu.c
index aae1d18..542db7f 100644
--- a/video/out/gpu/libmpv_gpu.c
+++ b/video/out/gpu/libmpv_gpu.c
@@ -185,7 +185,7 @@ static int render(struct render_backend *ctx, mpv_render_param *params,
&(int){0});
struct ra_fbo target = {.tex = tex, .flip = flip};
- gl_video_render_frame(p->renderer, frame, target, RENDER_FRAME_DEF);
+ gl_video_render_frame(p->renderer, frame, &target, RENDER_FRAME_DEF);
p->context->fns->done_frame(p->context, frame->display_synced);
return 0;
diff --git a/video/out/gpu/osd.c b/video/out/gpu/osd.c
index 91505a9..7892904 100644
--- a/video/out/gpu/osd.c
+++ b/video/out/gpu/osd.c
@@ -286,7 +286,7 @@ static void get_3d_side_by_side(int stereo_mode, int div[2])
}
void mpgl_osd_draw_finish(struct mpgl_osd *ctx, int index,
- struct gl_shader_cache *sc, struct ra_fbo fbo)
+ struct gl_shader_cache *sc, const struct ra_fbo *fbo)
{
struct mpgl_osd_part *part = ctx->parts[index];
@@ -312,7 +312,7 @@ void mpgl_osd_draw_finish(struct mpgl_osd *ctx, int index,
const int *factors = &blend_factors[part->format][0];
gl_sc_blend(sc, factors[0], factors[1], factors[2], factors[3]);
- gl_sc_dispatch_draw(sc, fbo.tex, false, vertex_vao, MP_ARRAY_SIZE(vertex_vao),
+ gl_sc_dispatch_draw(sc, fbo->tex, false, vertex_vao, MP_ARRAY_SIZE(vertex_vao),
sizeof(struct vertex), part->vertices, part->num_vertices);
}
diff --git a/video/out/gpu/osd.h b/video/out/gpu/osd.h
index 00fbc49..1b05e25 100644
--- a/video/out/gpu/osd.h
+++ b/video/out/gpu/osd.h
@@ -18,7 +18,7 @@ void mpgl_osd_resize(struct mpgl_osd *ctx, struct mp_osd_res res, int stereo_mod
bool mpgl_osd_draw_prepare(struct mpgl_osd *ctx, int index,
struct gl_shader_cache *sc);
void mpgl_osd_draw_finish(struct mpgl_osd *ctx, int index,
- struct gl_shader_cache *sc, struct ra_fbo fbo);
+ struct gl_shader_cache *sc, const struct ra_fbo *fbo);
bool mpgl_osd_check_change(struct mpgl_osd *ctx, struct mp_osd_res *res,
double pts);
diff --git a/video/out/gpu/ra.h b/video/out/gpu/ra.h
index 5f229f8..c0c58ac 100644
--- a/video/out/gpu/ra.h
+++ b/video/out/gpu/ra.h
@@ -143,8 +143,8 @@ struct ra_tex_params {
// be true depends on ra_format.linear_filter)
bool src_repeat; // if false, clamp texture coordinates to edge
// if true, repeat texture coordinates
- bool non_normalized; // hack for GL_TEXTURE_RECTANGLE OSX idiocy
- // always set to false, except in OSX code
+ bool non_normalized; // hack for GL_TEXTURE_RECTANGLE macOS idiocy
+ // always set to false, except in macOS code
bool external_oes; // hack for GL_TEXTURE_EXTERNAL_OES idiocy
// If non-NULL, the texture will be created with these contents. Using
// this does *not* require setting host_mutable. Otherwise, the initial
diff --git a/video/out/gpu/spirv.c b/video/out/gpu/spirv.c
index 67088bc..6910049 100644
--- a/video/out/gpu/spirv.c
+++ b/video/out/gpu/spirv.c
@@ -16,6 +16,7 @@ static const struct spirv_compiler_fns *compilers[] = {
#if HAVE_SHADERC
[SPIRV_SHADERC] = &spirv_shaderc,
#endif
+ NULL
};
static const struct m_opt_choice_alternatives compiler_choices[] = {
diff --git a/video/out/gpu/user_shaders.c b/video/out/gpu/user_shaders.c
index 708de87..f2507b6 100644
--- a/video/out/gpu/user_shaders.c
+++ b/video/out/gpu/user_shaders.c
@@ -431,7 +431,7 @@ static bool parse_tex(struct mp_log *log, struct ra *ra, struct bstr *body,
void parse_user_shader(struct mp_log *log, struct ra *ra, struct bstr shader,
void *priv,
- bool (*dohook)(void *p, struct gl_user_shader_hook hook),
+ bool (*dohook)(void *p, const struct gl_user_shader_hook *hook),
bool (*dotex)(void *p, struct gl_user_shader_tex tex))
{
if (!dohook || !dotex || !shader.len)
@@ -457,7 +457,7 @@ void parse_user_shader(struct mp_log *log, struct ra *ra, struct bstr shader,
}
struct gl_user_shader_hook h;
- if (!parse_hook(log, &shader, &h) || !dohook(priv, h))
+ if (!parse_hook(log, &shader, &h) || !dohook(priv, &h))
return;
}
}
diff --git a/video/out/gpu/user_shaders.h b/video/out/gpu/user_shaders.h
index 4bb7c22..d3405a8 100644
--- a/video/out/gpu/user_shaders.h
+++ b/video/out/gpu/user_shaders.h
@@ -88,7 +88,7 @@ struct gl_user_shader_tex {
// valid shader block parsed.
void parse_user_shader(struct mp_log *log, struct ra *ra, struct bstr shader,
void *priv,
- bool (*dohook)(void *p, struct gl_user_shader_hook hook),
+ bool (*dohook)(void *p, const struct gl_user_shader_hook *hook),
bool (*dotex)(void *p, struct gl_user_shader_tex tex));
// Evaluate a szexp, given a lookup function for named textures
diff --git a/video/out/gpu/utils.c b/video/out/gpu/utils.c
index 8a1aacf..d18cf6e 100644
--- a/video/out/gpu/utils.c
+++ b/video/out/gpu/utils.c
@@ -33,10 +33,10 @@ void gl_transform_trans(struct gl_transform t, struct gl_transform *x)
gl_transform_vec(t, &x->t[0], &x->t[1]);
}
-void gl_transform_ortho_fbo(struct gl_transform *t, struct ra_fbo fbo)
+void gl_transform_ortho_fbo(struct gl_transform *t, const struct ra_fbo *fbo)
{
- int y_dir = fbo.flip ? -1 : 1;
- gl_transform_ortho(t, 0, fbo.tex->params.w, 0, fbo.tex->params.h * y_dir);
+ int y_dir = fbo->flip ? -1 : 1;
+ gl_transform_ortho(t, 0, fbo->tex->params.w, 0, fbo->tex->params.h * y_dir);
}
float gl_video_scale_ambient_lux(float lmin, float lmax,
diff --git a/video/out/gpu/utils.h b/video/out/gpu/utils.h
index 215873e..dd52c38 100644
--- a/video/out/gpu/utils.h
+++ b/video/out/gpu/utils.h
@@ -63,7 +63,7 @@ static inline bool gl_transform_eq(struct gl_transform a, struct gl_transform b)
void gl_transform_trans(struct gl_transform t, struct gl_transform *x);
-void gl_transform_ortho_fbo(struct gl_transform *t, struct ra_fbo fbo);
+void gl_transform_ortho_fbo(struct gl_transform *t, const struct ra_fbo *fbo);
float gl_video_scale_ambient_lux(float lmin, float lmax,
float rmin, float rmax, float lux);
diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c
index 852ee78..1478ec4 100644
--- a/video/out/gpu/video.c
+++ b/video/out/gpu/video.c
@@ -183,6 +183,7 @@ struct gl_video {
struct mp_image_params real_image_params; // configured format
struct mp_image_params image_params; // texture format (mind hwdec case)
+ struct mp_image_params target_params; // target format
struct ra_imgfmt_desc ra_format; // texture format
int plane_count;
@@ -212,6 +213,7 @@ struct gl_video {
struct ra_tex *merge_tex[4];
struct ra_tex *scale_tex[4];
struct ra_tex *integer_tex[4];
+ struct ra_tex *chroma_tex[4];
struct ra_tex *indirect_tex;
struct ra_tex *blend_subs_tex;
struct ra_tex *error_diffusion_tex[2];
@@ -312,8 +314,8 @@ static const struct gl_video_opts gl_video_opts_def = {
.linear_downscaling = true,
.sigmoid_upscaling = true,
.interpolation_threshold = 0.01,
- .alpha_mode = ALPHA_BLEND_TILES,
- .background = {0, 0, 0, 255},
+ .background = BACKGROUND_TILES,
+ .background_color = {0, 0, 0, 255},
.gamma = 1.0f,
.tone_map = {
.curve = TONE_MAPPING_AUTO,
@@ -329,14 +331,9 @@ static const struct gl_video_opts gl_video_opts_def = {
.hwdec_interop = "auto",
};
-static int validate_scaler_opt(struct mp_log *log, const m_option_t *opt,
- struct bstr name, const char **value);
-
-static int validate_window_opt(struct mp_log *log, const m_option_t *opt,
- struct bstr name, const char **value);
-
-static int validate_error_diffusion_opt(struct mp_log *log, const m_option_t *opt,
- struct bstr name, const char **value);
+static OPT_STRING_VALIDATE_FUNC(validate_scaler_opt);
+static OPT_STRING_VALIDATE_FUNC(validate_window_opt);
+static OPT_STRING_VALIDATE_FUNC(validate_error_diffusion_opt);
#define OPT_BASE_STRUCT struct gl_video_opts
@@ -368,13 +365,13 @@ const struct m_sub_options gl_video_conf = {
.deprecation_message = "no replacement"},
{"gamma-auto", OPT_BOOL(gamma_auto),
.deprecation_message = "no replacement"},
- {"target-prim", OPT_CHOICE_C(target_prim, mp_csp_prim_names)},
- {"target-trc", OPT_CHOICE_C(target_trc, mp_csp_trc_names)},
+ {"target-prim", OPT_CHOICE_C(target_prim, pl_csp_prim_names)},
+ {"target-trc", OPT_CHOICE_C(target_trc, pl_csp_trc_names)},
{"target-peak", OPT_CHOICE(target_peak, {"auto", 0}),
M_RANGE(10, 10000)},
{"target-contrast", OPT_CHOICE(target_contrast, {"auto", 0}, {"inf", -1}),
M_RANGE(10, 1000000)},
- {"target-gamut", OPT_CHOICE_C(target_gamut, mp_csp_prim_names)},
+ {"target-gamut", OPT_CHOICE_C(target_gamut, pl_csp_prim_names)},
{"tone-mapping", OPT_CHOICE(tone_map.curve,
{"auto", TONE_MAPPING_AUTO},
{"clip", TONE_MAPPING_CLIP},
@@ -447,13 +444,12 @@ const struct m_sub_options gl_video_conf = {
M_RANGE(1, 128)},
{"error-diffusion",
OPT_STRING_VALIDATE(error_diffusion, validate_error_diffusion_opt)},
- {"alpha", OPT_CHOICE(alpha_mode,
- {"no", ALPHA_NO},
- {"yes", ALPHA_YES},
- {"blend", ALPHA_BLEND},
- {"blend-tiles", ALPHA_BLEND_TILES})},
+ {"background", OPT_CHOICE(background,
+ {"none", BACKGROUND_NONE},
+ {"color", BACKGROUND_COLOR},
+ {"tiles", BACKGROUND_TILES})},
{"opengl-rectangle-textures", OPT_BOOL(use_rectangle)},
- {"background", OPT_COLOR(background)},
+ {"background-color", OPT_COLOR(background_color)},
{"interpolation", OPT_BOOL(interpolation)},
{"interpolation-threshold", OPT_FLOAT(interpolation_threshold)},
{"blend-subtitles", OPT_CHOICE(blend_subs,
@@ -483,6 +479,7 @@ const struct m_sub_options gl_video_conf = {
},
.size = sizeof(struct gl_video_opts),
.defaults = &gl_video_opts_def,
+ .change_flags = UPDATE_VIDEO,
};
static void uninit_rendering(struct gl_video *p);
@@ -578,6 +575,7 @@ static void uninit_rendering(struct gl_video *p)
ra_tex_free(p->ra, &p->merge_tex[n]);
ra_tex_free(p->ra, &p->scale_tex[n]);
ra_tex_free(p->ra, &p->integer_tex[n]);
+ ra_tex_free(p->ra, &p->chroma_tex[n]);
}
ra_tex_free(p->ra, &p->indirect_tex);
@@ -605,15 +603,6 @@ bool gl_video_gamma_auto_enabled(struct gl_video *p)
return p->opts.gamma_auto;
}
-struct mp_colorspace gl_video_get_output_colorspace(struct gl_video *p)
-{
- return (struct mp_colorspace) {
- .primaries = p->opts.target_prim,
- .gamma = p->opts.target_trc,
- .hdr.max_luma = p->opts.target_peak,
- };
-}
-
// Warning: profile.start must point to a ta allocation, and the function
// takes over ownership.
void gl_video_set_icc_profile(struct gl_video *p, bstr icc_data)
@@ -627,8 +616,8 @@ bool gl_video_icc_auto_enabled(struct gl_video *p)
return p->opts.icc_opts ? p->opts.icc_opts->profile_auto : false;
}
-static bool gl_video_get_lut3d(struct gl_video *p, enum mp_csp_prim prim,
- enum mp_csp_trc trc)
+static bool gl_video_get_lut3d(struct gl_video *p, enum pl_color_primaries prim,
+ enum pl_color_transfer trc)
{
if (!p->use_lut_3d)
return false;
@@ -771,16 +760,16 @@ static void pass_get_images(struct gl_video *p, struct video_image *vimg,
struct gl_transform chroma = {{{ls_w, 0.0}, {0.0, ls_h}}};
- if (p->image_params.chroma_location != MP_CHROMA_CENTER) {
- int cx, cy;
- mp_get_chroma_location(p->image_params.chroma_location, &cx, &cy);
+ if (p->image_params.chroma_location != PL_CHROMA_CENTER) {
+ float cx, cy;
+ pl_chroma_location_offset(p->image_params.chroma_location, &cx, &cy);
// By default texture coordinates are such that chroma is centered with
// any chroma subsampling. If a specific direction is given, make it
// so that the luma and chroma sample line up exactly.
// For 4:4:4, setting chroma location should have no effect at all.
// luma sample size (in chroma coord. space)
- chroma.t[0] = ls_w < 1 ? ls_w * -cx / 2 : 0;
- chroma.t[1] = ls_h < 1 ? ls_h * -cy / 2 : 0;
+ chroma.t[0] = ls_w < 1 ? ls_w * -cx : 0;
+ chroma.t[1] = ls_h < 1 ? ls_h * -cy : 0;
}
memset(img, 0, 4 * sizeof(img[0]));
@@ -796,9 +785,9 @@ static void pass_get_images(struct gl_video *p, struct video_image *vimg,
ctype = PLANE_NONE;
} else if (c == 4) {
ctype = PLANE_ALPHA;
- } else if (p->image_params.color.space == MP_CSP_RGB) {
+ } else if (p->image_params.repr.sys == PL_COLOR_SYSTEM_RGB) {
ctype = PLANE_RGB;
- } else if (p->image_params.color.space == MP_CSP_XYZ) {
+ } else if (p->image_params.repr.sys == PL_COLOR_SYSTEM_XYZ) {
ctype = PLANE_XYZ;
} else {
ctype = c == 1 ? PLANE_LUMA : PLANE_CHROMA;
@@ -810,7 +799,7 @@ static void pass_get_images(struct gl_video *p, struct video_image *vimg,
int msb_valid_bits =
p->ra_format.component_bits + MPMIN(p->ra_format.component_pad, 0);
- int csp = type == PLANE_ALPHA ? MP_CSP_RGB : p->image_params.color.space;
+ int csp = type == PLANE_ALPHA ? PL_COLOR_SYSTEM_RGB : p->image_params.repr.sys;
float tex_mul =
1.0 / mp_get_csp_mul(csp, msb_valid_bits, p->ra_format.component_bits);
if (p->ra_format.component_type == RA_CTYPE_FLOAT)
@@ -1065,13 +1054,13 @@ static void uninit_video(struct gl_video *p)
ra_hwdec_mapper_free(&p->hwdec_mapper);
}
-static void pass_record(struct gl_video *p, struct mp_pass_perf perf)
+static void pass_record(struct gl_video *p, const struct mp_pass_perf *perf)
{
if (!p->pass || p->pass_idx == VO_PASS_PERF_MAX)
return;
struct pass_info *pass = &p->pass[p->pass_idx];
- pass->perf = perf;
+ pass->perf = *perf;
if (pass->desc.len == 0)
bstr_xappend(p, &pass->desc, bstr0("(unknown)"));
@@ -1211,12 +1200,13 @@ static void dispatch_compute(struct gl_video *p, int w, int h,
if (!(p->ra->caps & RA_CAP_NUM_GROUPS))
PRELUDE("#define gl_NumWorkGroups uvec3(%d, %d, 1)\n", num_x, num_y);
- pass_record(p, gl_sc_dispatch_compute(p->sc, num_x, num_y, 1));
+ struct mp_pass_perf perf = gl_sc_dispatch_compute(p->sc, num_x, num_y, 1);
+ pass_record(p, &perf);
cleanup_binds(p);
}
static struct mp_pass_perf render_pass_quad(struct gl_video *p,
- struct ra_fbo fbo, bool discard,
+ const struct ra_fbo *fbo, bool discard,
const struct mp_rect *dst)
{
// The first element is reserved for `vec2 position`
@@ -1274,15 +1264,16 @@ static struct mp_pass_perf render_pass_quad(struct gl_video *p,
&p->tmp_vertex[num_vertex_attribs * 1],
vertex_stride);
- return gl_sc_dispatch_draw(p->sc, fbo.tex, discard, p->vao, num_vertex_attribs,
+ return gl_sc_dispatch_draw(p->sc, fbo->tex, discard, p->vao, num_vertex_attribs,
vertex_stride, p->tmp_vertex, num_vertices);
}
-static void finish_pass_fbo(struct gl_video *p, struct ra_fbo fbo,
+static void finish_pass_fbo(struct gl_video *p, const struct ra_fbo *fbo,
bool discard, const struct mp_rect *dst)
{
pass_prepare_src_tex(p);
- pass_record(p, render_pass_quad(p, fbo, discard, dst));
+ struct mp_pass_perf perf = render_pass_quad(p, fbo, discard, dst);
+ pass_record(p, &perf);
debug_check_gl(p, "after rendering");
cleanup_binds(p);
}
@@ -1319,7 +1310,7 @@ static void finish_pass_tex(struct gl_video *p, struct ra_tex **dst_tex,
debug_check_gl(p, "after dispatching compute shader");
} else {
struct ra_fbo fbo = { .tex = *dst_tex, };
- finish_pass_fbo(p, fbo, true, &(struct mp_rect){0, 0, w, h});
+ finish_pass_fbo(p, &fbo, true, &(struct mp_rect){0, 0, w, h});
}
}
@@ -1955,7 +1946,7 @@ static void deband_hook(struct gl_video *p, struct image img,
{
pass_describe(p, "debanding (%s)", plane_names[img.type]);
pass_sample_deband(p->sc, p->opts.deband_opts, &p->lfg,
- p->image_params.color.gamma);
+ p->image_params.color.transfer);
}
static void unsharp_hook(struct gl_video *p, struct image img,
@@ -2046,25 +2037,23 @@ static void user_hook(struct gl_video *p, struct image img,
gl_transform_trans(shader->offset, trans);
}
-static bool add_user_hook(void *priv, struct gl_user_shader_hook hook)
+static bool add_user_hook(void *priv, const struct gl_user_shader_hook *hook)
{
struct gl_video *p = priv;
- struct gl_user_shader_hook *copy = talloc_ptrtype(p, copy);
- *copy = hook;
-
+ struct gl_user_shader_hook *copy = talloc_dup(p, (struct gl_user_shader_hook *)hook);
struct tex_hook texhook = {
- .save_tex = bstrdup0(copy, hook.save_tex),
- .components = hook.components,
- .align_offset = hook.align_offset,
+ .save_tex = bstrdup0(copy, copy->save_tex),
+ .components = copy->components,
+ .align_offset = copy->align_offset,
.hook = user_hook,
.cond = user_hook_cond,
.priv = copy,
};
for (int h = 0; h < SHADER_MAX_HOOKS; h++)
- texhook.hook_tex[h] = bstrdup0(copy, hook.hook_tex[h]);
+ texhook.hook_tex[h] = bstrdup0(copy, copy->hook_tex[h]);
for (int h = 0; h < SHADER_MAX_BINDS; h++)
- texhook.bind_tex[h] = bstrdup0(copy, hook.bind_tex[h]);
+ texhook.bind_tex[h] = bstrdup0(copy, copy->bind_tex[h]);
MP_TARRAY_APPEND(p, p->tex_hooks, p->num_tex_hooks, texhook);
return true;
@@ -2213,6 +2202,23 @@ static void pass_read_video(struct gl_video *p)
}
}
+ // If chroma textures are in a subsampled semi-planar format and rotated,
+ // introduce an explicit conversion pass to avoid breaking chroma scalers.
+ for (int n = 0; n < 4; n++) {
+ if (img[n].tex && img[n].type == PLANE_CHROMA &&
+ img[n].tex->params.format->num_components == 2 &&
+ p->image_params.rotate % 180 == 90 &&
+ p->ra_format.chroma_w != 1)
+ {
+ GLSLF("// chroma fix for rotated plane %d\n", n);
+ copy_image(p, &(int){0}, img[n]);
+ pass_describe(p, "chroma fix for rotated plane");
+ finish_pass_tex(p, &p->chroma_tex[n], img[n].w, img[n].h);
+ img[n] = image_wrap(p->chroma_tex[n], img[n].type,
+ img[n].components);
+ }
+ }
+
// At this point all planes are finalized but they may not be at the
// required size yet. Furthermore, they may have texture offsets that
// require realignment.
@@ -2345,29 +2351,29 @@ static void pass_convert_yuv(struct gl_video *p)
GLSLF("color = color.%s;\n", p->color_swizzle);
// Pre-colormatrix input gamma correction
- if (cparams.color.space == MP_CSP_XYZ)
- pass_linearize(p->sc, p->image_params.color.gamma);
+ if (cparams.repr.sys == PL_COLOR_SYSTEM_XYZ)
+ pass_linearize(p->sc, p->image_params.color.transfer);
// We always explicitly normalize the range in pass_read_video
cparams.input_bits = cparams.texture_bits = 0;
// Conversion to RGB. For RGB itself, this still applies e.g. brightness
// and contrast controls, or expansion of e.g. LSB-packed 10 bit data.
- struct mp_cmat m = {{{0}}};
+ struct pl_transform3x3 m = {0};
mp_get_csp_matrix(&cparams, &m);
- gl_sc_uniform_mat3(sc, "colormatrix", true, &m.m[0][0]);
+ gl_sc_uniform_mat3(sc, "colormatrix", true, &m.mat.m[0][0]);
gl_sc_uniform_vec3(sc, "colormatrix_c", m.c);
GLSL(color.rgb = mat3(colormatrix) * color.rgb + colormatrix_c;)
- if (cparams.color.space == MP_CSP_XYZ) {
- pass_delinearize(p->sc, p->image_params.color.gamma);
+ if (cparams.repr.sys == PL_COLOR_SYSTEM_XYZ) {
+ pass_delinearize(p->sc, p->image_params.color.transfer);
// mp_get_csp_matrix implicitly converts XYZ to DCI-P3
- p->image_params.color.space = MP_CSP_RGB;
- p->image_params.color.primaries = MP_CSP_PRIM_DCI_P3;
+ p->image_params.repr.sys = PL_COLOR_SYSTEM_RGB;
+ p->image_params.color.primaries = PL_COLOR_PRIM_DCI_P3;
}
- if (p->image_params.color.space == MP_CSP_BT_2020_C) {
+ if (p->image_params.repr.sys == PL_COLOR_SYSTEM_BT_2020_C) {
// Conversion for C'rcY'cC'bc via the BT.2020 CL system:
// C'bc = (B'-Y'c) / 1.9404 | C'bc <= 0
// = (B'-Y'c) / 1.5816 | C'bc > 0
@@ -2404,9 +2410,9 @@ static void pass_convert_yuv(struct gl_video *p)
}
p->components = 3;
- if (!p->has_alpha || p->opts.alpha_mode == ALPHA_NO) {
+ if (!p->has_alpha) {
GLSL(color.a = 1.0;)
- } else if (p->image_params.alpha == MP_ALPHA_PREMUL) {
+ } else if (p->image_params.repr.alpha == PL_ALPHA_PREMULTIPLIED) {
p->components = 4;
} else {
p->components = 4;
@@ -2491,7 +2497,7 @@ static void pass_scale_main(struct gl_video *p)
// Linear light downscaling results in nasty artifacts for HDR curves
// due to the potentially extreme brightness differences severely
// compounding any ringing. So just scale in gamma light instead.
- if (mp_trc_is_hdr(p->image_params.color.gamma))
+ if (pl_color_space_is_hdr(&p->image_params.color))
use_linear = false;
} else if (upscaling) {
use_linear = p->opts.linear_upscaling || p->opts.sigmoid_upscaling;
@@ -2499,7 +2505,7 @@ static void pass_scale_main(struct gl_video *p)
if (use_linear) {
p->use_linear = true;
- pass_linearize(p->sc, p->image_params.color.gamma);
+ pass_linearize(p->sc, p->image_params.color.transfer);
pass_opt_hook_point(p, "LINEAR", NULL);
}
@@ -2552,8 +2558,9 @@ static void pass_scale_main(struct gl_video *p)
// rendering)
// If OSD is true, ignore any changes that may have been made to the video
// by previous passes (i.e. linear scaling)
-static void pass_colormanage(struct gl_video *p, struct mp_colorspace src,
- struct mp_colorspace fbo_csp, int flags, bool osd)
+static void pass_colormanage(struct gl_video *p, struct pl_color_space src,
+ enum mp_csp_light src_light,
+ struct pl_color_space fbo_csp, int flags, bool osd)
{
struct ra *ra = p->ra;
@@ -2561,18 +2568,17 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src,
// unless specific transfer function, primaries or target peak
// is set. If values are set to _AUTO, the most likely intended
// values are guesstimated later in this function.
- struct mp_colorspace dst = {
- .gamma = p->opts.target_trc == MP_CSP_TRC_AUTO ?
- fbo_csp.gamma : p->opts.target_trc,
- .primaries = p->opts.target_prim == MP_CSP_PRIM_AUTO ?
+ struct pl_color_space dst = {
+ .transfer = p->opts.target_trc == PL_COLOR_TRC_UNKNOWN ?
+ fbo_csp.transfer : p->opts.target_trc,
+ .primaries = p->opts.target_prim == PL_COLOR_PRIM_UNKNOWN ?
fbo_csp.primaries : p->opts.target_prim,
- .light = MP_CSP_LIGHT_DISPLAY,
.hdr.max_luma = !p->opts.target_peak ?
fbo_csp.hdr.max_luma : p->opts.target_peak,
};
if (!p->colorspace_override_warned &&
- ((fbo_csp.gamma && dst.gamma != fbo_csp.gamma) ||
+ ((fbo_csp.transfer && dst.transfer != fbo_csp.transfer) ||
(fbo_csp.primaries && dst.primaries != fbo_csp.primaries)))
{
MP_WARN(p, "One or more colorspace value is being overridden "
@@ -2580,44 +2586,44 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src,
"transfer function: (dst: %s, fbo: %s), "
"primaries: (dst: %s, fbo: %s). "
"Rendering can lead to incorrect results!\n",
- m_opt_choice_str(mp_csp_trc_names, dst.gamma),
- m_opt_choice_str(mp_csp_trc_names, fbo_csp.gamma),
- m_opt_choice_str(mp_csp_prim_names, dst.primaries),
- m_opt_choice_str(mp_csp_prim_names, fbo_csp.primaries));
+ m_opt_choice_str(pl_csp_trc_names, dst.transfer),
+ m_opt_choice_str(pl_csp_trc_names, fbo_csp.transfer),
+ m_opt_choice_str(pl_csp_prim_names, dst.primaries),
+ m_opt_choice_str(pl_csp_prim_names, fbo_csp.primaries));
p->colorspace_override_warned = true;
}
- if (dst.gamma == MP_CSP_TRC_HLG)
- dst.light = MP_CSP_LIGHT_SCENE_HLG;
+ enum mp_csp_light dst_light = dst.transfer == PL_COLOR_TRC_HLG ?
+ MP_CSP_LIGHT_SCENE_HLG : MP_CSP_LIGHT_DISPLAY;
if (p->use_lut_3d && (flags & RENDER_SCREEN_COLOR)) {
// The 3DLUT is always generated against the video's original source
// space, *not* the reference space. (To avoid having to regenerate
// the 3DLUT for the OSD on every frame)
- enum mp_csp_prim prim_orig = p->image_params.color.primaries;
- enum mp_csp_trc trc_orig = p->image_params.color.gamma;
+ enum pl_color_primaries prim_orig = p->image_params.color.primaries;
+ enum pl_color_transfer trc_orig = p->image_params.color.transfer;
// One exception: HDR is not implemented by LittleCMS for technical
// limitation reasons, so we use a gamma 2.2 input curve here instead.
// We could pick any value we want here, the difference is just coding
// efficiency.
- if (mp_trc_is_hdr(trc_orig))
- trc_orig = MP_CSP_TRC_GAMMA22;
+ if (pl_color_space_is_hdr(&p->image_params.color))
+ trc_orig = PL_COLOR_TRC_GAMMA22;
if (gl_video_get_lut3d(p, prim_orig, trc_orig)) {
dst.primaries = prim_orig;
- dst.gamma = trc_orig;
- assert(dst.primaries && dst.gamma);
+ dst.transfer = trc_orig;
+ assert(dst.primaries && dst.transfer);
}
}
- if (dst.primaries == MP_CSP_PRIM_AUTO) {
+ if (dst.primaries == PL_COLOR_PRIM_UNKNOWN) {
// The vast majority of people are on sRGB or BT.709 displays, so pick
// this as the default output color space.
- dst.primaries = MP_CSP_PRIM_BT_709;
+ dst.primaries = PL_COLOR_PRIM_BT_709;
- if (src.primaries == MP_CSP_PRIM_BT_601_525 ||
- src.primaries == MP_CSP_PRIM_BT_601_625)
+ if (src.primaries == PL_COLOR_PRIM_BT_601_525 ||
+ src.primaries == PL_COLOR_PRIM_BT_601_625)
{
// Since we auto-pick BT.601 and BT.709 based on the dimensions,
// combined with the fact that they're very similar to begin with,
@@ -2627,28 +2633,28 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src,
}
}
- if (dst.gamma == MP_CSP_TRC_AUTO) {
+ if (dst.transfer == PL_COLOR_TRC_UNKNOWN) {
// Most people seem to complain when the image is darker or brighter
// than what they're "used to", so just avoid changing the gamma
// altogether by default. The only exceptions to this rule apply to
// very unusual TRCs, which even hardcode technoluddites would probably
// not enjoy viewing unaltered.
- dst.gamma = src.gamma;
+ dst.transfer = src.transfer;
// Avoid outputting linear light or HDR content "by default". For these
// just pick gamma 2.2 as a default, since it's a good estimate for
// the response of typical displays
- if (dst.gamma == MP_CSP_TRC_LINEAR || mp_trc_is_hdr(dst.gamma))
- dst.gamma = MP_CSP_TRC_GAMMA22;
+ if (dst.transfer == PL_COLOR_TRC_LINEAR || pl_color_space_is_hdr(&dst))
+ dst.transfer = PL_COLOR_TRC_GAMMA22;
}
// If there's no specific signal peak known for the output display, infer
// it from the chosen transfer function. Also normalize the src peak, in
// case it was unknown
if (!dst.hdr.max_luma)
- dst.hdr.max_luma = mp_trc_nom_peak(dst.gamma) * MP_REF_WHITE;
+ dst.hdr.max_luma = pl_color_transfer_nominal_peak(dst.transfer) * MP_REF_WHITE;
if (!src.hdr.max_luma)
- src.hdr.max_luma = mp_trc_nom_peak(src.gamma) * MP_REF_WHITE;
+ src.hdr.max_luma = pl_color_transfer_nominal_peak(src.transfer) * MP_REF_WHITE;
// Whitelist supported modes
switch (p->opts.tone_map.curve) {
@@ -2680,7 +2686,7 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src,
}
struct gl_tone_map_opts tone_map = p->opts.tone_map;
- bool detect_peak = tone_map.compute_peak >= 0 && mp_trc_is_hdr(src.gamma)
+ bool detect_peak = tone_map.compute_peak >= 0 && pl_color_space_is_hdr(&src)
&& src.hdr.max_luma > dst.hdr.max_luma;
if (detect_peak && !p->hdr_peak_ssbo) {
@@ -2719,7 +2725,22 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src,
}
// Adapt from src to dst as necessary
- pass_color_map(p->sc, p->use_linear && !osd, src, dst, &tone_map);
+ pass_color_map(p->sc, p->use_linear && !osd, src, dst, src_light, dst_light, &tone_map);
+
+ if (!osd) {
+ struct mp_csp_params cparams = MP_CSP_PARAMS_DEFAULTS;
+ mp_csp_equalizer_state_get(p->video_eq, &cparams);
+ if (cparams.levels_out == PL_COLOR_LEVELS_UNKNOWN)
+ cparams.levels_out = PL_COLOR_LEVELS_FULL;
+ p->target_params = (struct mp_image_params){
+ .imgfmt_name = p->fbo_format ? p->fbo_format->name : "unknown",
+ .w = p->texture_w,
+ .h = p->texture_h,
+ .color = dst,
+ .repr = {.sys = PL_COLOR_SYSTEM_RGB, .levels = cparams.levels_out},
+ .rotate = p->image_params.rotate,
+ };
+ }
if (p->use_lut_3d && (flags & RENDER_SCREEN_COLOR)) {
gl_sc_uniform_texture(p->sc, "lut_3d", p->lut_3d_texture);
@@ -2735,7 +2756,7 @@ void gl_video_set_fb_depth(struct gl_video *p, int fb_depth)
p->fb_depth = fb_depth;
}
-static void pass_dither(struct gl_video *p)
+static void pass_dither(struct gl_video *p, const struct ra_fbo *fbo)
{
// Assume 8 bits per component if unknown.
int dst_depth = p->fb_depth > 0 ? p->fb_depth : 8;
@@ -2868,7 +2889,9 @@ static void pass_dither(struct gl_video *p)
gl_sc_uniform_texture(p->sc, "dither", p->dither_texture);
- GLSLF("vec2 dither_pos = gl_FragCoord.xy * 1.0/%d.0;\n", dither_size);
+ GLSLF("vec2 dither_coord = vec2(gl_FragCoord.x, %d.0 + %f * gl_FragCoord.y);",
+ fbo->flip ? fbo->tex->params.h : 0, fbo->flip ? -1.0 : 1.0);
+ GLSLF("vec2 dither_pos = dither_coord * 1.0/%d.0;\n", dither_size);
if (p->opts.temporal_dither) {
int phase = (p->frames_rendered / p->opts.temporal_dither_period) % 8u;
@@ -2891,7 +2914,7 @@ static void pass_dither(struct gl_video *p)
// Draws the OSD, in scene-referred colors.. If cms is true, subtitles are
// instead adapted to the display's gamut.
static void pass_draw_osd(struct gl_video *p, int osd_flags, int frame_flags,
- double pts, struct mp_osd_res rect, struct ra_fbo fbo,
+ double pts, struct mp_osd_res rect, const struct ra_fbo *fbo,
bool cms)
{
if (frame_flags & RENDER_FRAME_VF_SUBS)
@@ -2910,20 +2933,21 @@ static void pass_draw_osd(struct gl_video *p, int osd_flags, int frame_flags,
// When subtitles need to be color managed, assume they're in sRGB
// (for lack of anything saner to do)
if (cms) {
- static const struct mp_colorspace csp_srgb = {
- .primaries = MP_CSP_PRIM_BT_709,
- .gamma = MP_CSP_TRC_SRGB,
- .light = MP_CSP_LIGHT_DISPLAY,
+ static const struct pl_color_space csp_srgb = {
+ .primaries = PL_COLOR_PRIM_BT_709,
+ .transfer = PL_COLOR_TRC_SRGB,
};
- pass_colormanage(p, csp_srgb, fbo.color_space, frame_flags, true);
+ pass_colormanage(p, csp_srgb, MP_CSP_LIGHT_DISPLAY, fbo->color_space,
+ frame_flags, true);
}
mpgl_osd_draw_finish(p->osd, n, p->sc, fbo);
}
timer_pool_stop(p->osd_timer);
pass_describe(p, "drawing osd");
- pass_record(p, timer_pool_measure(p->osd_timer));
+ struct mp_pass_perf perf = timer_pool_measure(p->osd_timer);
+ pass_record(p, &perf);
}
static float chroma_realign(int size, int pixel)
@@ -3013,7 +3037,7 @@ static bool pass_render_frame(struct gl_video *p, struct mp_image *mpi,
};
finish_pass_tex(p, &p->blend_subs_tex, rect.w, rect.h);
struct ra_fbo fbo = { p->blend_subs_tex };
- pass_draw_osd(p, OSD_DRAW_SUB_ONLY, flags, vpts, rect, fbo, false);
+ pass_draw_osd(p, OSD_DRAW_SUB_ONLY, flags, vpts, rect, &fbo, false);
pass_read_tex(p, p->blend_subs_tex);
pass_describe(p, "blend subs video");
}
@@ -3040,12 +3064,12 @@ static bool pass_render_frame(struct gl_video *p, struct mp_image *mpi,
rect.mt *= scale[1]; rect.mb *= scale[1];
// We should always blend subtitles in non-linear light
if (p->use_linear) {
- pass_delinearize(p->sc, p->image_params.color.gamma);
+ pass_delinearize(p->sc, p->image_params.color.transfer);
p->use_linear = false;
}
finish_pass_tex(p, &p->blend_subs_tex, p->texture_w, p->texture_h);
struct ra_fbo fbo = { p->blend_subs_tex };
- pass_draw_osd(p, OSD_DRAW_SUB_ONLY, flags, vpts, rect, fbo, false);
+ pass_draw_osd(p, OSD_DRAW_SUB_ONLY, flags, vpts, rect, &fbo, false);
pass_read_tex(p, p->blend_subs_tex);
pass_describe(p, "blend subs");
}
@@ -3055,7 +3079,7 @@ static bool pass_render_frame(struct gl_video *p, struct mp_image *mpi,
return true;
}
-static void pass_draw_to_screen(struct gl_video *p, struct ra_fbo fbo, int flags)
+static void pass_draw_to_screen(struct gl_video *p, const struct ra_fbo *fbo, int flags)
{
if (p->dumb_mode)
pass_render_frame_dumb(p);
@@ -3067,7 +3091,8 @@ static void pass_draw_to_screen(struct gl_video *p, struct ra_fbo fbo, int flags
GLSL(color.rgb = pow(color.rgb, vec3(user_gamma));)
}
- pass_colormanage(p, p->image_params.color, fbo.color_space, flags, false);
+ pass_colormanage(p, p->image_params.color, p->image_params.light,
+ fbo->color_space, flags, false);
// Since finish_pass_fbo doesn't work with compute shaders, and neither
// does the checkerboard/dither code, we may need an indirection via
@@ -3080,28 +3105,30 @@ static void pass_draw_to_screen(struct gl_video *p, struct ra_fbo fbo, int flags
copy_image(p, &(int){0}, tmp);
}
- if (p->has_alpha){
- if (p->opts.alpha_mode == ALPHA_BLEND_TILES) {
+ if (p->has_alpha) {
+ if (p->opts.background == BACKGROUND_TILES) {
// Draw checkerboard pattern to indicate transparency
GLSLF("// transparency checkerboard\n");
- GLSL(bvec2 tile = lessThan(fract(gl_FragCoord.xy * 1.0/32.0), vec2(0.5));)
+ GLSLF("vec2 tile_coord = vec2(gl_FragCoord.x, %d.0 + %f * gl_FragCoord.y);",
+ fbo->flip ? fbo->tex->params.h : 0, fbo->flip ? -1.0 : 1.0);
+ GLSL(bvec2 tile = lessThan(fract(tile_coord * 1.0 / 32.0), vec2(0.5));)
GLSL(vec3 background = vec3(tile.x == tile.y ? 0.93 : 0.87);)
GLSL(color.rgb += background.rgb * (1.0 - color.a);)
GLSL(color.a = 1.0;)
- } else if (p->opts.alpha_mode == ALPHA_BLEND) {
+ } else if (p->opts.background == BACKGROUND_COLOR) {
// Blend into background color (usually black)
- struct m_color c = p->opts.background;
+ struct m_color c = p->opts.background_color;
GLSLF("vec4 background = vec4(%f, %f, %f, %f);\n",
c.r / 255.0, c.g / 255.0, c.b / 255.0, c.a / 255.0);
- GLSL(color.rgb += background.rgb * (1.0 - color.a);)
- GLSL(color.a = background.a;)
+ GLSL(color += background * (1.0 - color.a);)
+ GLSL(color.rgb *= vec3(color.a););
}
}
pass_opt_hook_point(p, "OUTPUT", NULL);
if (flags & RENDER_SCREEN_COLOR)
- pass_dither(p);
+ pass_dither(p, fbo);
pass_describe(p, "output to screen");
finish_pass_fbo(p, fbo, false, &p->dst_rect);
}
@@ -3122,7 +3149,7 @@ static bool update_surface(struct gl_video *p, struct mp_image *mpi,
// because mixing in compressed light artificially darkens the results
if (!p->use_linear) {
p->use_linear = true;
- pass_linearize(p->sc, p->image_params.color.gamma);
+ pass_linearize(p->sc, p->image_params.color.transfer);
}
finish_pass_tex(p, &surf->tex, vp_w, vp_h);
@@ -3134,7 +3161,7 @@ static bool update_surface(struct gl_video *p, struct mp_image *mpi,
// Draws an interpolate frame to fbo, based on the frame timing in t
// flags: bit set of RENDER_FRAME_* flags
static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
- struct ra_fbo fbo, int flags)
+ const struct ra_fbo *fbo, int flags)
{
bool is_new = false;
@@ -3201,7 +3228,7 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
struct mp_image *f = t->frames[i];
uint64_t f_id = t->frame_id + i;
- if (!mp_image_params_equal(&f->params, &p->real_image_params))
+ if (!mp_image_params_static_equal(&f->params, &p->real_image_params))
continue;
if (f_id > p->surfaces[p->surface_idx].id) {
@@ -3306,11 +3333,11 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
}
void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame,
- struct ra_fbo fbo, int flags)
+ const struct ra_fbo *fbo, int flags)
{
gl_video_update_options(p);
- struct mp_rect target_rc = {0, 0, fbo.tex->params.w, fbo.tex->params.h};
+ struct mp_rect target_rc = {0, 0, fbo->tex->params.w, fbo->tex->params.h};
p->broken_frame = false;
@@ -3318,12 +3345,15 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame,
struct m_color c = p->clear_color;
float clear_color[4] = {c.r / 255.0, c.g / 255.0, c.b / 255.0, c.a / 255.0};
- p->ra->fns->clear(p->ra, fbo.tex, clear_color, &target_rc);
+ clear_color[0] *= clear_color[3];
+ clear_color[1] *= clear_color[3];
+ clear_color[2] *= clear_color[3];
+ p->ra->fns->clear(p->ra, fbo->tex, clear_color, &target_rc);
if (p->hwdec_overlay) {
if (has_frame) {
float *color = p->hwdec_overlay->overlay_colorkey;
- p->ra->fns->clear(p->ra, fbo.tex, color, &p->dst_rect);
+ p->ra->fns->clear(p->ra, fbo->tex, color, &p->dst_rect);
}
p->hwdec_overlay->driver->overlay_frame(p->hwdec_overlay, frame->current,
@@ -3364,43 +3394,41 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame,
// For the non-interpolation case, we draw to a single "cache"
// texture to speed up subsequent re-draws (if any exist)
- struct ra_fbo dest_fbo = fbo;
bool repeats = frame->num_vsyncs > 1 && frame->display_synced;
+ bool r = false;
if ((repeats || frame->still) && !p->dumb_mode &&
- (p->ra->caps & RA_CAP_BLIT) && fbo.tex->params.blit_dst)
+ (p->ra->caps & RA_CAP_BLIT) && fbo->tex->params.blit_dst)
{
// Attempt to use the same format as the destination FBO
// if possible. Some RAs use a wrapped dummy format here,
// so fall back to the fbo_format in that case.
- const struct ra_format *fmt = fbo.tex->params.format;
+ const struct ra_format *fmt = fbo->tex->params.format;
if (fmt->dummy_format)
fmt = p->fbo_format;
-
- bool r = ra_tex_resize(p->ra, p->log, &p->output_tex,
- fbo.tex->params.w, fbo.tex->params.h,
- fmt);
- if (r) {
- dest_fbo = (struct ra_fbo) { p->output_tex };
- p->output_tex_valid = true;
- }
+ r = ra_tex_resize(p->ra, p->log, &p->output_tex,
+ fbo->tex->params.w, fbo->tex->params.h,
+ fmt);
}
+ const struct ra_fbo *dest_fbo = r ? &(struct ra_fbo) { p->output_tex } : fbo;
+ p->output_tex_valid = r;
pass_draw_to_screen(p, dest_fbo, flags);
}
// "output tex valid" and "output tex needed" are equivalent
- if (p->output_tex_valid && fbo.tex->params.blit_dst) {
+ if (p->output_tex_valid && fbo->tex->params.blit_dst) {
pass_info_reset(p, true);
pass_describe(p, "redraw cached frame");
struct mp_rect src = p->dst_rect;
struct mp_rect dst = src;
- if (fbo.flip) {
- dst.y0 = fbo.tex->params.h - src.y0;
- dst.y1 = fbo.tex->params.h - src.y1;
+ if (fbo->flip) {
+ dst.y0 = fbo->tex->params.h - src.y0;
+ dst.y1 = fbo->tex->params.h - src.y1;
}
timer_pool_start(p->blit_timer);
- p->ra->fns->blit(p->ra, fbo.tex, p->output_tex, &dst, &src);
+ p->ra->fns->blit(p->ra, fbo->tex, p->output_tex, &dst, &src);
timer_pool_stop(p->blit_timer);
- pass_record(p, timer_pool_measure(p->blit_timer));
+ struct mp_pass_perf perf = timer_pool_measure(p->blit_timer);
+ pass_record(p, &perf);
}
}
}
@@ -3431,7 +3459,7 @@ done:
// Make the screen solid blue to make it visually clear that an
// error has occurred
float color[4] = {0.0, 0.05, 0.5, 1.0};
- p->ra->fns->clear(p->ra, fbo.tex, color, &target_rc);
+ p->ra->fns->clear(p->ra, fbo->tex, color, &target_rc);
}
p->frames_rendered++;
@@ -3522,7 +3550,7 @@ void gl_video_screenshot(struct gl_video *p, struct vo_frame *frame,
flags |= RENDER_FRAME_OSD;
if (args->scaled)
flags |= RENDER_SCREEN_COLOR;
- gl_video_render_frame(p, nframe, (struct ra_fbo){target}, flags);
+ gl_video_render_frame(p, nframe, &(struct ra_fbo){target}, flags);
res = mp_image_alloc(mpfmt, params.w, params.h);
if (!res)
@@ -3636,7 +3664,8 @@ static bool pass_upload_image(struct gl_video *p, struct mp_image *mpi, uint64_t
timer_pool_start(p->upload_timer);
bool ok = ra_hwdec_mapper_map(p->hwdec_mapper, vimg->mpi) >= 0;
timer_pool_stop(p->upload_timer);
- pass_record(p, timer_pool_measure(p->upload_timer));
+ struct mp_pass_perf perf = timer_pool_measure(p->upload_timer);
+ pass_record(p, &perf);
vimg->hwdec_mapped = true;
if (ok) {
@@ -3708,7 +3737,8 @@ static bool pass_upload_image(struct gl_video *p, struct mp_image *mpi, uint64_t
bool using_pbo = p->ra->use_pbo || !(p->ra->caps & RA_CAP_DIRECT_UPLOAD);
const char *mode = p->using_dr_path ? "DR" : using_pbo ? "PBO" : "naive";
pass_describe(p, "upload frame (%s)", mode);
- pass_record(p, timer_pool_measure(p->upload_timer));
+ struct mp_pass_perf perf = timer_pool_measure(p->upload_timer);
+ pass_record(p, &perf);
return true;
@@ -3806,9 +3836,8 @@ static void check_gl_features(struct gl_video *p)
p->opts.dither_algo = DITHER_NONE;
MP_WARN(p, "Disabling dithering (no gl_FragCoord).\n");
}
- if (!have_fragcoord && p->opts.alpha_mode == ALPHA_BLEND_TILES) {
- p->opts.alpha_mode = ALPHA_BLEND;
- // Verbose, since this is the default setting
+ if (!have_fragcoord && p->opts.background == BACKGROUND_TILES) {
+ p->opts.background = BACKGROUND_COLOR;
MP_VERBOSE(p, "Disabling alpha checkerboard (no gl_FragCoord).\n");
}
if (!have_fbo && have_compute) {
@@ -3864,9 +3893,9 @@ static void check_gl_features(struct gl_video *p)
.gamma_auto = p->opts.gamma_auto,
.pbo = p->opts.pbo,
.fbo_format = p->opts.fbo_format,
- .alpha_mode = p->opts.alpha_mode,
- .use_rectangle = p->opts.use_rectangle,
.background = p->opts.background,
+ .use_rectangle = p->opts.use_rectangle,
+ .background_color = p->opts.background_color,
.dither_algo = p->opts.dither_algo,
.dither_depth = p->opts.dither_depth,
.dither_size = p->opts.dither_size,
@@ -3913,8 +3942,8 @@ static void check_gl_features(struct gl_video *p)
}
}
- int use_cms = p->opts.target_prim != MP_CSP_PRIM_AUTO ||
- p->opts.target_trc != MP_CSP_TRC_AUTO || p->use_lut_3d;
+ int use_cms = p->opts.target_prim != PL_COLOR_PRIM_UNKNOWN ||
+ p->opts.target_trc != PL_COLOR_TRC_UNKNOWN || p->use_lut_3d;
// mix() is needed for some gamma functions
if (!have_mglsl && (p->opts.linear_downscaling ||
@@ -3926,8 +3955,8 @@ static void check_gl_features(struct gl_video *p)
MP_WARN(p, "Disabling linear/sigmoid scaling (GLSL version too old).\n");
}
if (!have_mglsl && use_cms) {
- p->opts.target_prim = MP_CSP_PRIM_AUTO;
- p->opts.target_trc = MP_CSP_TRC_AUTO;
+ p->opts.target_prim = PL_COLOR_PRIM_UNKNOWN;
+ p->opts.target_trc = PL_COLOR_TRC_UNKNOWN;
p->use_lut_3d = false;
MP_WARN(p, "Disabling color management (GLSL version too old).\n");
}
@@ -4022,7 +4051,7 @@ void gl_video_config(struct gl_video *p, struct mp_image_params *params)
unmap_overlay(p);
unref_current_image(p);
- if (!mp_image_params_equal(&p->real_image_params, params)) {
+ if (!mp_image_params_static_equal(&p->real_image_params, params)) {
uninit_video(p);
p->real_image_params = *params;
p->image_params = *params;
@@ -4117,7 +4146,7 @@ static void reinit_from_options(struct gl_video *p)
p->opts = *(struct gl_video_opts *)p->opts_cache->opts;
if (!p->force_clear_color)
- p->clear_color = p->opts.background;
+ p->clear_color = p->opts.background_color;
check_gl_features(p);
uninit_rendering(p);
@@ -4362,3 +4391,8 @@ void gl_video_load_hwdecs_for_img_fmt(struct gl_video *p, struct mp_hwdec_device
assert(p->hwdec_ctx.ra_ctx);
ra_hwdec_ctx_load_fmt(&p->hwdec_ctx, devs, params);
}
+
+struct mp_image_params *gl_video_get_target_params_ptr(struct gl_video *p)
+{
+ return &p->target_params;
+}
diff --git a/video/out/gpu/video.h b/video/out/gpu/video.h
index 411d336..66ccd9c 100644
--- a/video/out/gpu/video.h
+++ b/video/out/gpu/video.h
@@ -72,11 +72,10 @@ enum dither_algo {
DITHER_ERROR_DIFFUSION,
};
-enum alpha_mode {
- ALPHA_NO = 0,
- ALPHA_YES,
- ALPHA_BLEND,
- ALPHA_BLEND_TILES,
+enum background_type {
+ BACKGROUND_NONE = 0,
+ BACKGROUND_COLOR,
+ BACKGROUND_TILES,
};
enum blend_subs_mode {
@@ -155,9 +154,9 @@ struct gl_video_opts {
int temporal_dither_period;
char *error_diffusion;
char *fbo_format;
- int alpha_mode;
+ int background;
bool use_rectangle;
- struct m_color background;
+ struct m_color background_color;
bool interpolation;
float interpolation_threshold;
int blend_subs;
@@ -195,7 +194,7 @@ void gl_video_set_osd_source(struct gl_video *p, struct osd_state *osd);
bool gl_video_check_format(struct gl_video *p, int mp_format);
void gl_video_config(struct gl_video *p, struct mp_image_params *params);
void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame,
- struct ra_fbo fbo, int flags);
+ const struct ra_fbo *fbo, int flags);
void gl_video_resize(struct gl_video *p,
struct mp_rect *src, struct mp_rect *dst,
struct mp_osd_res *osd);
@@ -215,7 +214,6 @@ void gl_video_set_ambient_lux(struct gl_video *p, int lux);
void gl_video_set_icc_profile(struct gl_video *p, bstr icc_data);
bool gl_video_icc_auto_enabled(struct gl_video *p);
bool gl_video_gamma_auto_enabled(struct gl_video *p);
-struct mp_colorspace gl_video_get_output_colorspace(struct gl_video *p);
void gl_video_reset(struct gl_video *p);
bool gl_video_showing_interpolated_frame(struct gl_video *p);
@@ -234,5 +232,6 @@ void gl_video_configure_queue(struct gl_video *p, struct vo *vo);
struct mp_image *gl_video_get_image(struct gl_video *p, int imgfmt, int w, int h,
int stride_align, int flags);
+struct mp_image_params *gl_video_get_target_params_ptr(struct gl_video *p);
#endif
diff --git a/video/out/gpu/video_shaders.c b/video/out/gpu/video_shaders.c
index 6c0e8a8..e202818 100644
--- a/video/out/gpu/video_shaders.c
+++ b/video/out/gpu/video_shaders.c
@@ -17,6 +17,8 @@
#include <math.h>
+#include <libplacebo/colorspace.h>
+
#include "video_shaders.h"
#include "video.h"
@@ -252,7 +254,7 @@ void pass_compute_polar(struct gl_shader_cache *sc, struct scaler *scaler,
static void bicubic_calcweights(struct gl_shader_cache *sc, const char *t, const char *s)
{
// Explanation of how bicubic scaling with only 4 texel fetches is done:
- // http://www.mate.tue.nl/mate/pdfs/10318.pdf
+ // <https://web.archive.org/web/20180720154854/http://www.mate.tue.nl/mate/pdfs/10318.pdf>
// 'Efficient GPU-Based Texture Interpolation using Uniform B-Splines'
// Explanation why this algorithm normally always blurs, even with unit
// scaling:
@@ -337,10 +339,10 @@ static const float SLOG_A = 0.432699,
//
// These functions always output to a normalized scale of [0,1], for
// convenience of the video.c code that calls it. To get the values in an
-// absolute scale, multiply the result by `mp_trc_nom_peak(trc)`
-void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
+// absolute scale, multiply the result by `pl_color_transfer_nominal_peak(trc)`
+void pass_linearize(struct gl_shader_cache *sc, enum pl_color_transfer trc)
{
- if (trc == MP_CSP_TRC_LINEAR)
+ if (trc == PL_COLOR_TRC_LINEAR)
return;
GLSLF("// linearize\n");
@@ -353,40 +355,40 @@ void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
GLSL(color.rgb = clamp(color.rgb, 0.0, 1.0);)
switch (trc) {
- case MP_CSP_TRC_SRGB:
+ case PL_COLOR_TRC_SRGB:
GLSLF("color.rgb = mix(color.rgb * vec3(1.0/12.92), \n"
" pow((color.rgb + vec3(0.055))/vec3(1.055), vec3(2.4)), \n"
" %s(lessThan(vec3(0.04045), color.rgb))); \n",
gl_sc_bvec(sc, 3));
break;
- case MP_CSP_TRC_BT_1886:
+ case PL_COLOR_TRC_BT_1886:
GLSL(color.rgb = pow(color.rgb, vec3(2.4));)
break;
- case MP_CSP_TRC_GAMMA18:
+ case PL_COLOR_TRC_GAMMA18:
GLSL(color.rgb = pow(color.rgb, vec3(1.8));)
break;
- case MP_CSP_TRC_GAMMA20:
+ case PL_COLOR_TRC_GAMMA20:
GLSL(color.rgb = pow(color.rgb, vec3(2.0));)
break;
- case MP_CSP_TRC_GAMMA22:
+ case PL_COLOR_TRC_GAMMA22:
GLSL(color.rgb = pow(color.rgb, vec3(2.2));)
break;
- case MP_CSP_TRC_GAMMA24:
+ case PL_COLOR_TRC_GAMMA24:
GLSL(color.rgb = pow(color.rgb, vec3(2.4));)
break;
- case MP_CSP_TRC_GAMMA26:
+ case PL_COLOR_TRC_GAMMA26:
GLSL(color.rgb = pow(color.rgb, vec3(2.6));)
break;
- case MP_CSP_TRC_GAMMA28:
+ case PL_COLOR_TRC_GAMMA28:
GLSL(color.rgb = pow(color.rgb, vec3(2.8));)
break;
- case MP_CSP_TRC_PRO_PHOTO:
+ case PL_COLOR_TRC_PRO_PHOTO:
GLSLF("color.rgb = mix(color.rgb * vec3(1.0/16.0), \n"
" pow(color.rgb, vec3(1.8)), \n"
" %s(lessThan(vec3(0.03125), color.rgb))); \n",
gl_sc_bvec(sc, 3));
break;
- case MP_CSP_TRC_PQ:
+ case PL_COLOR_TRC_PQ:
GLSLF("color.rgb = pow(color.rgb, vec3(1.0/%f));\n", PQ_M2);
GLSLF("color.rgb = max(color.rgb - vec3(%f), vec3(0.0)) \n"
" / (vec3(%f) - vec3(%f) * color.rgb);\n",
@@ -396,33 +398,33 @@ void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
// MP_REF_WHITE instead, so rescale
GLSLF("color.rgb *= vec3(%f);\n", 10000 / MP_REF_WHITE);
break;
- case MP_CSP_TRC_HLG:
+ case PL_COLOR_TRC_HLG:
GLSLF("color.rgb = mix(vec3(4.0) * color.rgb * color.rgb,\n"
" exp((color.rgb - vec3(%f)) * vec3(1.0/%f)) + vec3(%f),\n"
" %s(lessThan(vec3(0.5), color.rgb)));\n",
HLG_C, HLG_A, HLG_B, gl_sc_bvec(sc, 3));
GLSLF("color.rgb *= vec3(1.0/%f);\n", MP_REF_WHITE_HLG);
break;
- case MP_CSP_TRC_V_LOG:
+ case PL_COLOR_TRC_V_LOG:
GLSLF("color.rgb = mix((color.rgb - vec3(0.125)) * vec3(1.0/5.6), \n"
" pow(vec3(10.0), (color.rgb - vec3(%f)) * vec3(1.0/%f)) \n"
" - vec3(%f), \n"
" %s(lessThanEqual(vec3(0.181), color.rgb))); \n",
VLOG_D, VLOG_C, VLOG_B, gl_sc_bvec(sc, 3));
break;
- case MP_CSP_TRC_S_LOG1:
+ case PL_COLOR_TRC_S_LOG1:
GLSLF("color.rgb = pow(vec3(10.0), (color.rgb - vec3(%f)) * vec3(1.0/%f))\n"
" - vec3(%f);\n",
SLOG_C, SLOG_A, SLOG_B);
break;
- case MP_CSP_TRC_S_LOG2:
+ case PL_COLOR_TRC_S_LOG2:
GLSLF("color.rgb = mix((color.rgb - vec3(%f)) * vec3(1.0/%f), \n"
" (pow(vec3(10.0), (color.rgb - vec3(%f)) * vec3(1.0/%f)) \n"
" - vec3(%f)) * vec3(1.0/%f), \n"
" %s(lessThanEqual(vec3(%f), color.rgb))); \n",
SLOG_Q, SLOG_P, SLOG_C, SLOG_A, SLOG_B, SLOG_K2, gl_sc_bvec(sc, 3), SLOG_Q);
break;
- case MP_CSP_TRC_ST428:
+ case PL_COLOR_TRC_ST428:
GLSL(color.rgb = vec3(52.37/48.0) * pow(color.rgb, vec3(2.6)););
break;
default:
@@ -430,7 +432,7 @@ void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
}
// Rescale to prevent clipping on non-float textures
- GLSLF("color.rgb *= vec3(1.0/%f);\n", mp_trc_nom_peak(trc));
+ GLSLF("color.rgb *= vec3(1.0/%f);\n", pl_color_transfer_nominal_peak(trc));
}
// Delinearize (compress), given a TRC as output. This corresponds to the
@@ -438,51 +440,51 @@ void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
// reference monitor.
//
// Like pass_linearize, this functions ingests values on an normalized scale
-void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
+void pass_delinearize(struct gl_shader_cache *sc, enum pl_color_transfer trc)
{
- if (trc == MP_CSP_TRC_LINEAR)
+ if (trc == PL_COLOR_TRC_LINEAR)
return;
GLSLF("// delinearize\n");
GLSL(color.rgb = clamp(color.rgb, 0.0, 1.0);)
- GLSLF("color.rgb *= vec3(%f);\n", mp_trc_nom_peak(trc));
+ GLSLF("color.rgb *= vec3(%f);\n", pl_color_transfer_nominal_peak(trc));
switch (trc) {
- case MP_CSP_TRC_SRGB:
+ case PL_COLOR_TRC_SRGB:
GLSLF("color.rgb = mix(color.rgb * vec3(12.92), \n"
" vec3(1.055) * pow(color.rgb, vec3(1.0/2.4)) \n"
" - vec3(0.055), \n"
" %s(lessThanEqual(vec3(0.0031308), color.rgb))); \n",
gl_sc_bvec(sc, 3));
break;
- case MP_CSP_TRC_BT_1886:
+ case PL_COLOR_TRC_BT_1886:
GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.4));)
break;
- case MP_CSP_TRC_GAMMA18:
+ case PL_COLOR_TRC_GAMMA18:
GLSL(color.rgb = pow(color.rgb, vec3(1.0/1.8));)
break;
- case MP_CSP_TRC_GAMMA20:
+ case PL_COLOR_TRC_GAMMA20:
GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.0));)
break;
- case MP_CSP_TRC_GAMMA22:
+ case PL_COLOR_TRC_GAMMA22:
GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.2));)
break;
- case MP_CSP_TRC_GAMMA24:
+ case PL_COLOR_TRC_GAMMA24:
GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.4));)
break;
- case MP_CSP_TRC_GAMMA26:
+ case PL_COLOR_TRC_GAMMA26:
GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.6));)
break;
- case MP_CSP_TRC_GAMMA28:
+ case PL_COLOR_TRC_GAMMA28:
GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.8));)
break;
- case MP_CSP_TRC_PRO_PHOTO:
+ case PL_COLOR_TRC_PRO_PHOTO:
GLSLF("color.rgb = mix(color.rgb * vec3(16.0), \n"
" pow(color.rgb, vec3(1.0/1.8)), \n"
" %s(lessThanEqual(vec3(0.001953), color.rgb))); \n",
gl_sc_bvec(sc, 3));
break;
- case MP_CSP_TRC_PQ:
+ case PL_COLOR_TRC_PQ:
GLSLF("color.rgb *= vec3(1.0/%f);\n", 10000 / MP_REF_WHITE);
GLSLF("color.rgb = pow(color.rgb, vec3(%f));\n", PQ_M1);
GLSLF("color.rgb = (vec3(%f) + vec3(%f) * color.rgb) \n"
@@ -490,32 +492,32 @@ void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc)
PQ_C1, PQ_C2, PQ_C3);
GLSLF("color.rgb = pow(color.rgb, vec3(%f));\n", PQ_M2);
break;
- case MP_CSP_TRC_HLG:
+ case PL_COLOR_TRC_HLG:
GLSLF("color.rgb *= vec3(%f);\n", MP_REF_WHITE_HLG);
GLSLF("color.rgb = mix(vec3(0.5) * sqrt(color.rgb),\n"
" vec3(%f) * log(color.rgb - vec3(%f)) + vec3(%f),\n"
" %s(lessThan(vec3(1.0), color.rgb)));\n",
HLG_A, HLG_B, HLG_C, gl_sc_bvec(sc, 3));
break;
- case MP_CSP_TRC_V_LOG:
+ case PL_COLOR_TRC_V_LOG:
GLSLF("color.rgb = mix(vec3(5.6) * color.rgb + vec3(0.125), \n"
" vec3(%f) * log(color.rgb + vec3(%f)) \n"
" + vec3(%f), \n"
" %s(lessThanEqual(vec3(0.01), color.rgb))); \n",
VLOG_C / M_LN10, VLOG_B, VLOG_D, gl_sc_bvec(sc, 3));
break;
- case MP_CSP_TRC_S_LOG1:
+ case PL_COLOR_TRC_S_LOG1:
GLSLF("color.rgb = vec3(%f) * log(color.rgb + vec3(%f)) + vec3(%f);\n",
SLOG_A / M_LN10, SLOG_B, SLOG_C);
break;
- case MP_CSP_TRC_S_LOG2:
+ case PL_COLOR_TRC_S_LOG2:
GLSLF("color.rgb = mix(vec3(%f) * color.rgb + vec3(%f), \n"
" vec3(%f) * log(vec3(%f) * color.rgb + vec3(%f)) \n"
" + vec3(%f), \n"
" %s(lessThanEqual(vec3(0.0), color.rgb))); \n",
SLOG_P, SLOG_Q, SLOG_A / M_LN10, SLOG_K2, SLOG_B, SLOG_C, gl_sc_bvec(sc, 3));
break;
- case MP_CSP_TRC_ST428:
+ case PL_COLOR_TRC_ST428:
GLSL(color.rgb = pow(color.rgb * vec3(48.0/52.37), vec3(1.0/2.6)););
break;
default:
@@ -834,42 +836,42 @@ static void pass_tone_map(struct gl_shader_cache *sc,
// the caller to have already bound the appropriate SSBO and set up the compute
// shader metadata
void pass_color_map(struct gl_shader_cache *sc, bool is_linear,
- struct mp_colorspace src, struct mp_colorspace dst,
+ struct pl_color_space src, struct pl_color_space dst,
+ enum mp_csp_light src_light, enum mp_csp_light dst_light,
const struct gl_tone_map_opts *opts)
{
GLSLF("// color mapping\n");
// Some operations need access to the video's luma coefficients, so make
// them available
- float rgb2xyz[3][3];
- mp_get_rgb2xyz_matrix(mp_get_csp_primaries(src.primaries), rgb2xyz);
- gl_sc_uniform_vec3(sc, "src_luma", rgb2xyz[1]);
- mp_get_rgb2xyz_matrix(mp_get_csp_primaries(dst.primaries), rgb2xyz);
- gl_sc_uniform_vec3(sc, "dst_luma", rgb2xyz[1]);
-
- bool need_ootf = src.light != dst.light;
- if (src.light == MP_CSP_LIGHT_SCENE_HLG && src.hdr.max_luma != dst.hdr.max_luma)
+ pl_matrix3x3 rgb2xyz = pl_get_rgb2xyz_matrix(pl_raw_primaries_get(src.primaries));
+ gl_sc_uniform_vec3(sc, "src_luma", rgb2xyz.m[1]);
+ rgb2xyz = pl_get_rgb2xyz_matrix(pl_raw_primaries_get(dst.primaries));
+ gl_sc_uniform_vec3(sc, "dst_luma", rgb2xyz.m[1]);
+
+ bool need_ootf = src_light != dst_light;
+ if (src_light == MP_CSP_LIGHT_SCENE_HLG && src.hdr.max_luma != dst.hdr.max_luma)
need_ootf = true;
// All operations from here on require linear light as a starting point,
- // so we linearize even if src.gamma == dst.gamma when one of the other
+ // so we linearize even if src.gamma == dst.transfer when one of the other
// operations needs it
- bool need_linear = src.gamma != dst.gamma ||
+ bool need_linear = src.transfer != dst.transfer ||
src.primaries != dst.primaries ||
src.hdr.max_luma != dst.hdr.max_luma ||
need_ootf;
if (need_linear && !is_linear) {
// We also pull it up so that 1.0 is the reference white
- pass_linearize(sc, src.gamma);
+ pass_linearize(sc, src.transfer);
is_linear = true;
}
// Pre-scale the incoming values into an absolute scale
- GLSLF("color.rgb *= vec3(%f);\n", mp_trc_nom_peak(src.gamma));
+ GLSLF("color.rgb *= vec3(%f);\n", pl_color_transfer_nominal_peak(src.transfer));
if (need_ootf)
- pass_ootf(sc, src.light, src.hdr.max_luma / MP_REF_WHITE);
+ pass_ootf(sc, src_light, src.hdr.max_luma / MP_REF_WHITE);
// Tone map to prevent clipping due to excessive brightness
if (src.hdr.max_luma > dst.hdr.max_luma) {
@@ -879,11 +881,11 @@ void pass_color_map(struct gl_shader_cache *sc, bool is_linear,
// Adapt to the right colorspace if necessary
if (src.primaries != dst.primaries) {
- struct mp_csp_primaries csp_src = mp_get_csp_primaries(src.primaries),
- csp_dst = mp_get_csp_primaries(dst.primaries);
- float m[3][3] = {{0}};
- mp_get_cms_matrix(csp_src, csp_dst, MP_INTENT_RELATIVE_COLORIMETRIC, m);
- gl_sc_uniform_mat3(sc, "cms_matrix", true, &m[0][0]);
+ const struct pl_raw_primaries *csp_src = pl_raw_primaries_get(src.primaries),
+ *csp_dst = pl_raw_primaries_get(dst.primaries);
+ pl_matrix3x3 m = pl_get_color_mapping_matrix(csp_src, csp_dst,
+ PL_INTENT_RELATIVE_COLORIMETRIC);
+ gl_sc_uniform_mat3(sc, "cms_matrix", true, &m.m[0][0]);
GLSL(color.rgb = cms_matrix * color.rgb;)
if (!opts->gamut_mode || opts->gamut_mode == GAMUT_DESATURATE) {
@@ -900,14 +902,14 @@ void pass_color_map(struct gl_shader_cache *sc, bool is_linear,
}
if (need_ootf)
- pass_inverse_ootf(sc, dst.light, dst.hdr.max_luma / MP_REF_WHITE);
+ pass_inverse_ootf(sc, dst_light, dst.hdr.max_luma / MP_REF_WHITE);
// Post-scale the outgoing values from absolute scale to normalized.
// For SDR, we normalize to the chosen signal peak. For HDR, we normalize
// to the encoding range of the transfer function.
float dst_range = dst.hdr.max_luma / MP_REF_WHITE;
- if (mp_trc_is_hdr(dst.gamma))
- dst_range = mp_trc_nom_peak(dst.gamma);
+ if (pl_color_space_is_hdr(&dst))
+ dst_range = pl_color_transfer_nominal_peak(dst.transfer);
GLSLF("color.rgb *= vec3(%f);\n", 1.0 / dst_range);
@@ -919,7 +921,7 @@ void pass_color_map(struct gl_shader_cache *sc, bool is_linear,
}
if (is_linear)
- pass_delinearize(sc, dst.gamma);
+ pass_delinearize(sc, dst.transfer);
}
// Wide usage friendly PRNG, shamelessly stolen from a GLSL tricks forum post.
@@ -964,7 +966,7 @@ const struct m_sub_options deband_conf = {
// Stochastically sample a debanded result from a hooked texture.
void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts,
- AVLFG *lfg, enum mp_csp_trc trc)
+ AVLFG *lfg, enum pl_color_transfer trc)
{
// Initialize the PRNG
GLSLF("{\n");
@@ -1008,7 +1010,7 @@ void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts,
GLSL(noise.z = rand(h); h = permute(h);)
// Noise is scaled to the signal level to prevent extreme noise for HDR
- float gain = opts->grain/8192.0 / mp_trc_nom_peak(trc);
+ float gain = opts->grain/8192.0 / pl_color_transfer_nominal_peak(trc);
GLSLF("color.xyz += %f * (noise - vec3(0.5));\n", gain);
GLSLF("}\n");
}
diff --git a/video/out/gpu/video_shaders.h b/video/out/gpu/video_shaders.h
index 27e7874..7547df6 100644
--- a/video/out/gpu/video_shaders.h
+++ b/video/out/gpu/video_shaders.h
@@ -44,15 +44,16 @@ void pass_sample_bicubic_fast(struct gl_shader_cache *sc);
void pass_sample_oversample(struct gl_shader_cache *sc, struct scaler *scaler,
int w, int h);
-void pass_linearize(struct gl_shader_cache *sc, enum mp_csp_trc trc);
-void pass_delinearize(struct gl_shader_cache *sc, enum mp_csp_trc trc);
+void pass_linearize(struct gl_shader_cache *sc, enum pl_color_transfer trc);
+void pass_delinearize(struct gl_shader_cache *sc, enum pl_color_transfer trc);
void pass_color_map(struct gl_shader_cache *sc, bool is_linear,
- struct mp_colorspace src, struct mp_colorspace dst,
+ struct pl_color_space src, struct pl_color_space dst,
+ enum mp_csp_light src_light, enum mp_csp_light dst_light,
const struct gl_tone_map_opts *opts);
void pass_sample_deband(struct gl_shader_cache *sc, struct deband_opts *opts,
- AVLFG *lfg, enum mp_csp_trc trc);
+ AVLFG *lfg, enum pl_color_transfer trc);
void pass_sample_unsharp(struct gl_shader_cache *sc, float param);