vo_opengl, osd: allow osc.lua to react faster on resizes

Glitches when resizing are still possible, but are reduced. Other VOs
could support this too, but don't need to do so.

(Totally avoiding glitches would be much more effort, and probably not
worth the trouble. How about you just watch the video the player is
playing, instead of spending your time resizing the window.)
This commit is contained in:
wm4 2016-03-21 22:23:41 +01:00
parent 5f1ff78516
commit d6c99c8513
5 changed files with 55 additions and 16 deletions

View File

@ -212,6 +212,33 @@ void osd_set_external2(struct osd_state *osd, struct sub_bitmaps *imgs)
pthread_mutex_unlock(&osd->lock);
}
static void check_obj_resize(struct osd_state *osd, struct mp_osd_res res,
struct osd_object *obj)
{
if (!osd_res_equals(res, obj->vo_res)) {
obj->vo_res = res;
obj->force_redraw = true;
mp_client_broadcast_event(mp_client_api_get_core(osd->global->client_api),
MP_EVENT_WIN_RESIZE, NULL);
}
}
// Optional. Can be called for faster reaction of OSD-generating scripts like
// osc.lua. This can achieve that the resize happens first, so that the OSD is
// generated at the correct resolution the first time the resized frame is
// rendered. Since the OSD doesn't (and can't) wait for the script, this
// increases the time in which the script can react, and also gets rid of the
// unavoidable redraw delay (though it will still be racy).
// Unnecessary for anything else.
void osd_resize(struct osd_state *osd, struct mp_osd_res res)
{
pthread_mutex_lock(&osd->lock);
int types[] = {OSDTYPE_OSD, OSDTYPE_EXTERNAL, OSDTYPE_EXTERNAL2, -1};
for (int n = 0; types[n] >= 0; n++)
check_obj_resize(osd, res, osd->objs[types[n]]);
pthread_mutex_unlock(&osd->lock);
}
static void render_object(struct osd_state *osd, struct osd_object *obj,
struct mp_osd_res res, double video_pts,
const bool sub_formats[SUBBITMAP_COUNT],
@ -226,12 +253,7 @@ static void render_object(struct osd_state *osd, struct osd_object *obj,
*out_imgs = (struct sub_bitmaps) {0};
if (!osd_res_equals(res, obj->vo_res)) {
obj->vo_res = res;
obj->force_redraw = true;
mp_client_broadcast_event(mp_client_api_get_core(osd->global->client_api),
MP_EVENT_WIN_RESIZE, NULL);
}
check_obj_resize(osd, res, obj);
if (obj->type == OSDTYPE_SUB || obj->type == OSDTYPE_SUB2) {
if (obj->sub) {

View File

@ -176,6 +176,8 @@ void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res,
double video_pts, int draw_flags,
struct mp_image_pool *pool, struct mp_image *dest);
void osd_resize(struct osd_state *osd, struct mp_osd_res res);
struct mp_image_params;
struct mp_osd_res osd_res_from_image_params(const struct mp_image_params *p);

View File

@ -92,7 +92,7 @@ struct mpgl_osd {
int64_t change_counter;
// temporary
int stereo_mode;
int display_size[2];
struct mp_osd_res osd_res;
void *scratch;
};
@ -382,8 +382,8 @@ void mpgl_osd_draw_part(struct mpgl_osd *ctx, int vp_w, int vp_h, int index)
struct gl_transform t;
gl_transform_ortho(&t, 0, vp_w, 0, vp_h);
float a_x = ctx->display_size[0] * x;
float a_y = ctx->display_size[1] * y;
float a_x = ctx->osd_res.w * x;
float a_y = ctx->osd_res.h * y;
t.t[0] += a_x * t.m[0][0] + a_y * t.m[1][0];
t.t[1] += a_x * t.m[0][1] + a_y * t.m[1][1];
@ -403,20 +403,25 @@ struct gl_vao *mpgl_osd_get_vao(struct mpgl_osd *ctx)
return &ctx->vao;
}
static void set_res(struct mpgl_osd *ctx, struct mp_osd_res res, int stereo_mode)
{
int div[2];
get_3d_side_by_side(stereo_mode, div);
res.w /= div[0];
res.h /= div[1];
ctx->osd_res = res;
}
void mpgl_osd_generate(struct mpgl_osd *ctx, struct mp_osd_res res, double pts,
int stereo_mode, int draw_flags)
{
for (int n = 0; n < MAX_OSD_PARTS; n++)
ctx->parts[n]->num_subparts = 0;
int div[2];
get_3d_side_by_side(stereo_mode, div);
set_res(ctx, res, stereo_mode);
struct mp_osd_res s_res = res;
ctx->display_size[0] = s_res.w = s_res.w / div[0];
ctx->display_size[1] = s_res.h = s_res.h / div[1];
osd_draw(ctx->osd, s_res, pts, draw_flags, ctx->formats, gen_osd_cb, ctx);
osd_draw(ctx->osd, ctx->osd_res, pts, draw_flags, ctx->formats, gen_osd_cb, ctx);
ctx->stereo_mode = stereo_mode;
// Parts going away does not necessarily result in gen_osd_cb() being called
@ -429,6 +434,13 @@ void mpgl_osd_generate(struct mpgl_osd *ctx, struct mp_osd_res res, double pts,
}
}
// See osd_resize() for remarks. This function is an optional optimization too.
void mpgl_osd_resize(struct mpgl_osd *ctx, struct mp_osd_res res, int stereo_mode)
{
set_res(ctx, res, stereo_mode);
osd_resize(ctx->osd, ctx->osd_res);
}
int64_t mpgl_get_change_counter(struct mpgl_osd *ctx)
{
return ctx->change_counter;

View File

@ -14,6 +14,7 @@ void mpgl_osd_set_options(struct mpgl_osd *ctx, bool pbo);
void mpgl_osd_generate(struct mpgl_osd *ctx, struct mp_osd_res res, double pts,
int stereo_mode, int draw_flags);
void mpgl_osd_resize(struct mpgl_osd *ctx, struct mp_osd_res res, int stereo_mode);
enum sub_bitmap_format mpgl_osd_get_part_format(struct mpgl_osd *ctx, int index);
struct gl_vao *mpgl_osd_get_vao(struct mpgl_osd *ctx);
void mpgl_osd_draw_part(struct mpgl_osd *ctx, int vp_w, int vp_h, int index);

View File

@ -2448,6 +2448,8 @@ void gl_video_resize(struct gl_video *p, int vp_w, int vp_h,
p->vp_h = vp_h;
gl_video_reset_surfaces(p);
mpgl_osd_resize(p->osd, p->osd_rect, p->image_params.stereo_out);
}
static bool unmap_image(struct gl_video *p, struct mp_image *mpi)