diff options
Diffstat (limited to 'video/out/gl_video.c')
-rw-r--r-- | video/out/gl_video.c | 76 |
1 files changed, 60 insertions, 16 deletions
diff --git a/video/out/gl_video.c b/video/out/gl_video.c index d7fd6774b6..f0a6f60d84 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -165,9 +165,11 @@ struct gl_video { struct mp_imgfmt_desc image_desc; - bool is_yuv; + bool is_yuv, is_rgb; bool is_linear_rgb; + float input_gamma, conv_gamma; + // per pixel (full pixel when packed, each component when planar) int plane_bits; int plane_count; @@ -452,6 +454,11 @@ static void update_uniforms(struct gl_video *p, GLuint program) .texture_bits = (p->plane_bits + 7) & ~7, }; mp_csp_copy_equalizer_values(&cparams, &p->video_eq); + if (p->image_desc.flags & MP_IMGFLAG_XYZ) { + cparams.colorspace.format = MP_CSP_XYZ; + cparams.input_bits = 8; + cparams.texture_bits = 8; + } loc = gl->GetUniformLocation(program, "transform"); if (loc >= 0) { @@ -463,11 +470,16 @@ static void update_uniforms(struct gl_video *p, GLuint program) loc = gl->GetUniformLocation(program, "colormatrix"); if (loc >= 0) { float yuv2rgb[3][4] = {{0}}; - if (p->is_yuv) - mp_get_yuv2rgb_coeffs(&cparams, yuv2rgb); + mp_get_yuv2rgb_coeffs(&cparams, yuv2rgb); gl->UniformMatrix4x3fv(loc, 1, GL_TRUE, &yuv2rgb[0][0]); } + gl->Uniform1f(gl->GetUniformLocation(program, "input_gamma"), + p->input_gamma); + + gl->Uniform1f(gl->GetUniformLocation(program, "conv_gamma"), + p->conv_gamma); + gl->Uniform3f(gl->GetUniformLocation(program, "inv_gamma"), 1.0 / cparams.rgamma, 1.0 / cparams.ggamma, @@ -704,8 +716,22 @@ static void compile_shaders(struct gl_video *p) char *header_final = talloc_strdup(tmp, ""); char *header_sep = NULL; - bool convert_input_to_linear = !p->is_linear_rgb && - (p->opts.srgb || p->use_lut_3d); + float input_gamma = 1.0; + float conv_gamma = 1.0; + + if (p->image_desc.flags & MP_IMGFLAG_XYZ) { + input_gamma *= 2.6; + conv_gamma *= 1.0 / 2.2; + } + + if (!p->is_linear_rgb && (p->opts.srgb || p->use_lut_3d)) + conv_gamma *= 1.0 / 0.45; + + p->input_gamma = input_gamma; + p->conv_gamma = conv_gamma; + + bool convert_input_gamma = p->input_gamma != 1.0; + bool convert_input_to_linear = p->conv_gamma != 1.0; if (p->image_format == IMGFMT_NV12 || p->image_format == IMGFMT_NV21) { shader_def(&header_conv, "USE_CONV", "CONV_NV12"); @@ -716,8 +742,9 @@ static void compile_shaders(struct gl_video *p) shader_def_opt(&header_conv, "USE_GBRP", p->image_format == IMGFMT_GBRP); shader_def_opt(&header_conv, "USE_SWAP_UV", p->image_format == IMGFMT_NV21); shader_def_opt(&header_conv, "USE_YGRAY", p->is_yuv && p->plane_count == 1); - shader_def_opt(&header_conv, "USE_COLORMATRIX", p->is_yuv); - shader_def_opt(&header_conv, "USE_LINEAR_CONV", convert_input_to_linear); + shader_def_opt(&header_conv, "USE_INPUT_GAMMA", convert_input_gamma); + shader_def_opt(&header_conv, "USE_COLORMATRIX", !p->is_rgb); + shader_def_opt(&header_conv, "USE_CONV_GAMMA", convert_input_to_linear); if (p->opts.enable_alpha && p->plane_count == 4) shader_def(&header_conv, "USE_ALPHA_PLANE", "3"); @@ -745,7 +772,7 @@ static void compile_shaders(struct gl_video *p) // Don't sample from input video textures before converting the input to // linear light. (Unneeded when sRGB textures are used.) - if (convert_input_to_linear) + if (convert_input_gamma || convert_input_to_linear) use_indirect = true; // It doesn't make sense to scale the chroma with cscale in the 1. scale @@ -1048,7 +1075,7 @@ static void init_video(struct gl_video *p) check_gl_features(p); - if (!p->is_yuv && (p->opts.srgb || p->use_lut_3d)) { + if (p->is_rgb && (p->opts.srgb || p->use_lut_3d)) { p->is_linear_rgb = true; p->image.planes[0].gl_internal_format = GL_SRGB; } @@ -1398,18 +1425,15 @@ struct mp_image *gl_video_download_image(struct gl_video *p) return image; } -static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs) +static void draw_osd_cb(void *ctx, struct mpgl_osd_part *osd, + struct sub_bitmaps *imgs) { struct gl_video *p = ctx; GL *gl = p->gl; - struct mpgl_osd_part *osd = mpgl_osd_generate(p->osd, imgs); - if (!osd) - return; - assert(osd->format != SUBBITMAP_EMPTY); - if (!osd->num_vertices) { + if (!osd->num_vertices && imgs) { osd->vertices = talloc_realloc(osd, osd->vertices, struct vertex, osd->packer->count * VERTICES_PER_QUAD); @@ -1449,7 +1473,7 @@ void gl_video_draw_osd(struct gl_video *p, struct osd_state *osd) GL *gl = p->gl; assert(p->osd); - osd_draw(osd, p->osd_rect, osd->vo_pts, 0, p->osd->formats, draw_osd_cb, p); + mpgl_osd_draw_cb(p->osd, osd, p->osd_rect, draw_osd_cb, p); // The playloop calls this last before waiting some time until it decides // to call flip_page(). Tell OpenGL to start execution of the GPU commands @@ -1634,6 +1658,12 @@ static bool init_format(int fmt, struct gl_video *init) plane_format[0] = byte_formats[1]; } + // XYZ (same roganization as RGB packed, but requires conversion matrix) + if (!supported && fmt == IMGFMT_XYZ12) { + supported = true; + plane_format[0] = IMGFMT_RGB48; + } + // All formats in mp_to_gl_formats[] are supported // If it's not in the table, it will be rejected below. // Includes packed RGB and YUV formats @@ -1666,6 +1696,7 @@ static bool init_format(int fmt, struct gl_video *init) return false; init->is_yuv = desc.flags & MP_IMGFLAG_YUV; + init->is_rgb = desc.flags & MP_IMGFLAG_RGB; init->is_linear_rgb = false; init->plane_count = desc.num_planes; init->image_desc = desc; @@ -1797,3 +1828,16 @@ static int validate_scaler_opt(const m_option_t *opt, struct bstr name, snprintf(s, sizeof(s), "%.*s", BSTR_P(param)); return handle_scaler_opt(s) ? 1 : M_OPT_INVALID; } + +// Resize and redraw the contents of the window without further configuration. +// Intended to be used in situations where the frontend can't really be +// involved with reconfiguring the VO properly. +// gl_video_resize() should be called when user interaction is done. +void gl_video_resize_redraw(struct gl_video *p, int w, int h) +{ + p->gl->Viewport(p->vp_x, p->vp_y, w, h); + p->vp_w = w; + p->vp_h = h; + gl_video_render_frame(p); + mpgl_osd_redraw_cb(p->osd, draw_osd_cb, p); +} |