osd: simplify an aspect of change detection handling

There was a somewhat obscure optimization in the OSD and subtitle
rendering path: if only the position of the sub-images changed, and not
the actual image data, uploading of the image data could be skipped. In
theory, this could speed up things like scrolling subtitles.

But it turns out that even in the rare cases subtitles have such scrolls
or axis-aligned movement, modern libass rarely signals this kind of
change. Possibly this is because of sub-pixel handling and such, which
break this.

As such, it's a worthless optimization and just introduces additional
complexity and subtle bugs (especially in cases libass does the
opposite: incorrectly signaling a position change only, which happened
before). Remove this optimization, and rename bitmap_pos_id to
change_id.
This commit is contained in:
wm4
2015-03-18 12:33:14 +01:00
parent 15478ca31c
commit 51befc9deb
13 changed files with 74 additions and 100 deletions

View File

@@ -3931,7 +3931,7 @@ static void recreate_overlays(struct MPContext *mpctx)
if (new == cmd->overlay_osd_current) if (new == cmd->overlay_osd_current)
new += 1; // pick the unused one new += 1; // pick the unused one
new->format = SUBBITMAP_RGBA; new->format = SUBBITMAP_RGBA;
new->bitmap_id = new->bitmap_pos_id = 1; new->change_id = 1;
// overlay array can have unused entries, but parts list must be "packed" // overlay array can have unused entries, but parts list must be "packed"
new->num_parts = 0; new->num_parts = 0;
for (int n = 0; n < cmd->num_overlays; n++) { for (int n = 0; n < cmd->num_overlays; n++) {

View File

@@ -134,10 +134,8 @@ void mp_ass_render_frame(ASS_Renderer *renderer, ASS_Track *track, double time,
{ {
int changed; int changed;
ASS_Image *imgs = ass_render_frame(renderer, track, time, &changed); ASS_Image *imgs = ass_render_frame(renderer, track, time, &changed);
if (changed == 2) if (changed)
res->bitmap_id = ++res->bitmap_pos_id; res->change_id++;
else if (changed)
res->bitmap_pos_id++;
res->format = SUBBITMAP_LIBASS; res->format = SUBBITMAP_LIBASS;
res->parts = *parts; res->parts = *parts;

View File

@@ -43,7 +43,7 @@ struct sub_cache {
}; };
struct part { struct part {
int bitmap_pos_id; int change_id;
int imgfmt; int imgfmt;
enum mp_csp colorspace; enum mp_csp colorspace;
enum mp_csp_levels levels; enum mp_csp_levels levels;
@@ -399,7 +399,7 @@ static struct part *get_cache(struct mp_draw_sub_cache *cache,
if (use_cache) { if (use_cache) {
part = cache->parts[sbs->render_index]; part = cache->parts[sbs->render_index];
if (part) { if (part) {
if (part->bitmap_pos_id != sbs->bitmap_pos_id if (part->change_id != sbs->change_id
|| part->imgfmt != format->imgfmt || part->imgfmt != format->imgfmt
|| part->colorspace != format->params.colorspace || part->colorspace != format->params.colorspace
|| part->levels != format->params.colorlevels) || part->levels != format->params.colorlevels)
@@ -411,7 +411,7 @@ static struct part *get_cache(struct mp_draw_sub_cache *cache,
if (!part) { if (!part) {
part = talloc(cache, struct part); part = talloc(cache, struct part);
*part = (struct part) { *part = (struct part) {
.bitmap_pos_id = sbs->bitmap_pos_id, .change_id = sbs->change_id,
.num_imgs = sbs->num_parts, .num_imgs = sbs->num_parts,
.imgfmt = format->imgfmt, .imgfmt = format->imgfmt,
.levels = format->params.colorlevels, .levels = format->params.colorlevels,

View File

@@ -263,7 +263,7 @@ static void render_object(struct osd_state *osd, struct osd_object *obj,
} else if (obj->type == OSDTYPE_EXTERNAL2) { } else if (obj->type == OSDTYPE_EXTERNAL2) {
if (obj->external2 && obj->external2->format) { if (obj->external2 && obj->external2->format) {
*out_imgs = *obj->external2; *out_imgs = *obj->external2;
obj->external2->bitmap_id = obj->external2->bitmap_pos_id = 0; obj->external2->change_id = 0;
} }
} else if (obj->type == OSDTYPE_NAV_HIGHLIGHT) { } else if (obj->type == OSDTYPE_NAV_HIGHLIGHT) {
if (obj->highlight_priv) if (obj->highlight_priv)
@@ -272,29 +272,23 @@ static void render_object(struct osd_state *osd, struct osd_object *obj,
osd_object_get_bitmaps(osd, obj, out_imgs); osd_object_get_bitmaps(osd, obj, out_imgs);
} }
if (obj->force_redraw) { if (obj->force_redraw)
out_imgs->bitmap_id++; out_imgs->change_id++;
out_imgs->bitmap_pos_id++;
}
obj->force_redraw = false; obj->force_redraw = false;
obj->vo_bitmap_id += out_imgs->bitmap_id; obj->vo_change_id += out_imgs->change_id;
obj->vo_bitmap_pos_id += out_imgs->bitmap_pos_id;
if (out_imgs->num_parts == 0) if (out_imgs->num_parts == 0)
return; return;
if (obj->cached.bitmap_id == obj->vo_bitmap_id if (obj->cached.change_id == obj->vo_change_id && formats[obj->cached.format])
&& obj->cached.bitmap_pos_id == obj->vo_bitmap_pos_id
&& formats[obj->cached.format])
{ {
*out_imgs = obj->cached; *out_imgs = obj->cached;
return; return;
} }
out_imgs->render_index = obj->type; out_imgs->render_index = obj->type;
out_imgs->bitmap_id = obj->vo_bitmap_id; out_imgs->change_id = obj->vo_change_id;
out_imgs->bitmap_pos_id = obj->vo_bitmap_pos_id;
if (formats[out_imgs->format]) if (formats[out_imgs->format])
return; return;

View File

@@ -70,8 +70,7 @@ struct sub_bitmaps {
struct sub_bitmap *parts; struct sub_bitmap *parts;
int num_parts; int num_parts;
// Incremented on each change int change_id; // Incremented on each change
int bitmap_id, bitmap_pos_id;
}; };
struct mp_osd_res { struct mp_osd_res {

View File

@@ -36,8 +36,7 @@ struct osd_object {
struct sub_bitmaps cached; struct sub_bitmaps cached;
// VO cache state // VO cache state
int vo_bitmap_id; int vo_change_id;
int vo_bitmap_pos_id;
struct mp_osd_res vo_res; struct mp_osd_res vo_res;
// Internally used by osd_libass.c // Internally used by osd_libass.c

View File

@@ -256,7 +256,7 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts,
res->parts = priv->outbitmaps; res->parts = priv->outbitmaps;
res->num_parts = current->count; res->num_parts = current->count;
if (priv->displayed_id != current->id) if (priv->displayed_id != current->id)
res->bitmap_id = ++res->bitmap_pos_id; res->change_id++;
priv->displayed_id = current->id; priv->displayed_id = current->id;
res->format = SUBBITMAP_INDEXED; res->format = SUBBITMAP_INDEXED;

View File

@@ -68,7 +68,7 @@ static const struct gl_vao_entry vertex_vao[] = {
struct mpgl_osd_part { struct mpgl_osd_part {
enum sub_bitmap_format format; enum sub_bitmap_format format;
int bitmap_id, bitmap_pos_id; int change_id;
GLuint texture; GLuint texture;
int w, h; int w, h;
GLuint buffer; GLuint buffer;
@@ -278,14 +278,11 @@ static void gen_osd_cb(void *pctx, struct sub_bitmaps *imgs)
struct mpgl_osd_part *osd = ctx->parts[imgs->render_index]; struct mpgl_osd_part *osd = ctx->parts[imgs->render_index];
if (imgs->bitmap_pos_id != osd->bitmap_pos_id) { if (imgs->change_id != osd->change_id) {
if (imgs->bitmap_id != osd->bitmap_id) { if (!upload_osd(ctx, osd, imgs))
if (!upload_osd(ctx, osd, imgs)) osd->packer->count = 0;
osd->packer->count = 0;
}
osd->bitmap_id = imgs->bitmap_id; osd->change_id = imgs->change_id;
osd->bitmap_pos_id = imgs->bitmap_pos_id;
} }
osd->num_subparts = osd->packer->count; osd->num_subparts = osd->packer->count;

View File

@@ -103,7 +103,7 @@ struct texplane {
struct osdpart { struct osdpart {
enum sub_bitmap_format format; enum sub_bitmap_format format;
int bitmap_id, bitmap_pos_id; int change_id;
struct d3dtex texture; struct d3dtex texture;
int num_vertices; int num_vertices;
vertex_osd *vertices; vertex_osd *vertices;
@@ -453,7 +453,7 @@ static void destroy_d3d_surfaces(d3d_priv *priv)
for (int n = 0; n < MAX_OSD_PARTS; n++) { for (int n = 0; n < MAX_OSD_PARTS; n++) {
struct osdpart *osd = priv->osd[n]; struct osdpart *osd = priv->osd[n];
d3dtex_release(priv, &osd->texture); d3dtex_release(priv, &osd->texture);
osd->bitmap_id = osd->bitmap_pos_id = -1; osd->change_id = -1;
} }
if (priv->d3d_backbuf) if (priv->d3d_backbuf)
@@ -1618,14 +1618,11 @@ static struct osdpart *generate_osd(d3d_priv *priv, struct sub_bitmaps *imgs)
struct osdpart *osd = priv->osd[imgs->render_index]; struct osdpart *osd = priv->osd[imgs->render_index];
if (imgs->bitmap_pos_id != osd->bitmap_pos_id) { if (imgs->change_id != osd->change_id) {
if (imgs->bitmap_id != osd->bitmap_id) { if (!upload_osd(priv, osd, imgs))
if (!upload_osd(priv, osd, imgs)) osd->packer->count = 0;
osd->packer->count = 0;
}
osd->bitmap_id = imgs->bitmap_id; osd->change_id = imgs->change_id;
osd->bitmap_pos_id = imgs->bitmap_pos_id;
osd->num_vertices = 0; osd->num_vertices = 0;
} }

View File

@@ -177,8 +177,7 @@ struct priv {
struct mp_osd_res osd_res; struct mp_osd_res osd_res;
struct formatmap_entry osd_format; struct formatmap_entry osd_format;
struct osd_bitmap_surface { struct osd_bitmap_surface {
int bitmap_id; int change_id;
int bitmap_pos_id;
struct osd_target { struct osd_target {
SDL_Rect source; SDL_Rect source;
SDL_Rect dest; SDL_Rect dest;
@@ -702,7 +701,7 @@ static void generate_osd_part(struct vo *vo, struct sub_bitmaps *imgs)
if (imgs->format == SUBBITMAP_EMPTY || imgs->num_parts == 0) if (imgs->format == SUBBITMAP_EMPTY || imgs->num_parts == 0)
return; return;
if (imgs->bitmap_pos_id == sfc->bitmap_pos_id) if (imgs->change_id == sfc->change_id)
return; return;
if (imgs->num_parts > sfc->targets_size) { if (imgs->num_parts > sfc->targets_size) {
@@ -725,49 +724,46 @@ static void generate_osd_part(struct vo *vo, struct sub_bitmaps *imgs)
bmp->x, bmp->y, bmp->dw, bmp->dh bmp->x, bmp->y, bmp->dw, bmp->dh
}; };
if (imgs->bitmap_id != sfc->bitmap_id || !target->tex) { // tex: alpha blended texture
// tex: alpha blended texture if (target->tex) {
if (target->tex) { SDL_DestroyTexture(target->tex);
SDL_DestroyTexture(target->tex); target->tex = NULL;
target->tex = NULL; }
} if (!target->tex)
if (!target->tex) target->tex = SDL_CreateTexture(vc->renderer,
target->tex = SDL_CreateTexture(vc->renderer, vc->osd_format.sdl, SDL_TEXTUREACCESS_STREAMING,
vc->osd_format.sdl, SDL_TEXTUREACCESS_STREAMING, bmp->w, bmp->h);
bmp->w, bmp->h); if (!target->tex) {
if (!target->tex) { MP_ERR(vo, "Could not create texture\n");
MP_ERR(vo, "Could not create texture\n"); }
} if (target->tex) {
if (target->tex) { SDL_SetTextureBlendMode(target->tex,
SDL_SetTextureBlendMode(target->tex, SDL_BLENDMODE_BLEND);
SDL_BLENDMODE_BLEND); SDL_SetTextureColorMod(target->tex, 0, 0, 0);
SDL_SetTextureColorMod(target->tex, 0, 0, 0); subbitmap_to_texture(vo, target->tex, bmp, 0); // RGBA -> 000A
subbitmap_to_texture(vo, target->tex, bmp, 0); // RGBA -> 000A }
}
// tex2: added texture // tex2: added texture
if (target->tex2) { if (target->tex2) {
SDL_DestroyTexture(target->tex2); SDL_DestroyTexture(target->tex2);
target->tex2 = NULL; target->tex2 = NULL;
} }
if (!target->tex2) if (!target->tex2)
target->tex2 = SDL_CreateTexture(vc->renderer, target->tex2 = SDL_CreateTexture(vc->renderer,
vc->osd_format.sdl, SDL_TEXTUREACCESS_STREAMING, vc->osd_format.sdl, SDL_TEXTUREACCESS_STREAMING,
bmp->w, bmp->h); bmp->w, bmp->h);
if (!target->tex2) { if (!target->tex2) {
MP_ERR(vo, "Could not create texture\n"); MP_ERR(vo, "Could not create texture\n");
} }
if (target->tex2) { if (target->tex2) {
SDL_SetTextureBlendMode(target->tex2, SDL_SetTextureBlendMode(target->tex2,
SDL_BLENDMODE_ADD); SDL_BLENDMODE_ADD);
subbitmap_to_texture(vo, target->tex2, bmp, subbitmap_to_texture(vo, target->tex2, bmp,
0xFF000000); // RGBA -> RGB1 0xFF000000); // RGBA -> RGB1
}
} }
} }
sfc->bitmap_id = imgs->bitmap_id; sfc->change_id = imgs->change_id;
sfc->bitmap_pos_id = imgs->bitmap_pos_id;
} }
static void draw_osd_part(struct vo *vo, int index) static void draw_osd_part(struct vo *vo, int index)

View File

@@ -57,7 +57,7 @@ struct vaapi_subpic {
struct vaapi_osd_part { struct vaapi_osd_part {
bool active; bool active;
int bitmap_pos_id; int change_id;
struct vaapi_osd_image image; struct vaapi_osd_image image;
struct vaapi_subpic subpic; struct vaapi_subpic subpic;
struct osd_conv_cache *conv_cache; struct osd_conv_cache *conv_cache;
@@ -345,8 +345,8 @@ static void draw_osd_cb(void *pctx, struct sub_bitmaps *imgs)
struct priv *p = pctx; struct priv *p = pctx;
struct vaapi_osd_part *part = &p->osd_parts[imgs->render_index]; struct vaapi_osd_part *part = &p->osd_parts[imgs->render_index];
if (imgs->bitmap_pos_id != part->bitmap_pos_id) { if (imgs->change_id != part->change_id) {
part->bitmap_pos_id = imgs->bitmap_pos_id; part->change_id = imgs->change_id;
osd_scale_rgba(part->conv_cache, imgs); osd_scale_rgba(part->conv_cache, imgs);

View File

@@ -136,8 +136,7 @@ struct vdpctx {
} *targets; } *targets;
int targets_size; int targets_size;
int render_count; int render_count;
int bitmap_id; int change_id;
int bitmap_pos_id;
} osd_surfaces[MAX_OSD_PARTS]; } osd_surfaces[MAX_OSD_PARTS];
// Video equalizer // Video equalizer
@@ -388,7 +387,7 @@ static void mark_vdpau_objects_uninitialized(struct vo *vo)
for (int i = 0; i < MAX_OSD_PARTS; i++) { for (int i = 0; i < MAX_OSD_PARTS; i++) {
struct osd_bitmap_surface *sfc = &vc->osd_surfaces[i]; struct osd_bitmap_surface *sfc = &vc->osd_surfaces[i];
talloc_free(sfc->packer); talloc_free(sfc->packer);
sfc->bitmap_id = sfc->bitmap_pos_id = 0; sfc->change_id = 0;
*sfc = (struct osd_bitmap_surface){ *sfc = (struct osd_bitmap_surface){
.surface = VDP_INVALID_HANDLE, .surface = VDP_INVALID_HANDLE,
}; };
@@ -512,7 +511,7 @@ static void generate_osd_part(struct vo *vo, struct sub_bitmaps *imgs)
struct osd_bitmap_surface *sfc = &vc->osd_surfaces[imgs->render_index]; struct osd_bitmap_surface *sfc = &vc->osd_surfaces[imgs->render_index];
bool need_upload = false; bool need_upload = false;
if (imgs->bitmap_pos_id == sfc->bitmap_pos_id) if (imgs->change_id == sfc->change_id)
return; // Nothing changed and we still have the old data return; // Nothing changed and we still have the old data
sfc->render_count = 0; sfc->render_count = 0;
@@ -520,9 +519,6 @@ static void generate_osd_part(struct vo *vo, struct sub_bitmaps *imgs)
if (imgs->format == SUBBITMAP_EMPTY || imgs->num_parts == 0) if (imgs->format == SUBBITMAP_EMPTY || imgs->num_parts == 0)
return; return;
if (imgs->bitmap_id == sfc->bitmap_id)
goto osd_skip_upload;
need_upload = true; need_upload = true;
VdpRGBAFormat format; VdpRGBAFormat format;
int format_size; int format_size;
@@ -574,7 +570,6 @@ static void generate_osd_part(struct vo *vo, struct sub_bitmaps *imgs)
sfc->packer->used_height}); sfc->packer->used_height});
} }
osd_skip_upload:
if (sfc->surface == VDP_INVALID_HANDLE) if (sfc->surface == VDP_INVALID_HANDLE)
return; return;
if (sfc->packer->count > sfc->targets_size) { if (sfc->packer->count > sfc->targets_size) {
@@ -610,8 +605,7 @@ osd_skip_upload:
sfc->render_count++; sfc->render_count++;
} }
sfc->bitmap_id = imgs->bitmap_id; sfc->change_id = imgs->change_id;
sfc->bitmap_pos_id = imgs->bitmap_pos_id;
} }
static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs) static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)

View File

@@ -134,7 +134,7 @@ struct priv {
struct wl_subsurface *osd_subsurfaces[MAX_OSD_PARTS]; struct wl_subsurface *osd_subsurfaces[MAX_OSD_PARTS];
shm_buffer_t *osd_buffers[MAX_OSD_PARTS]; shm_buffer_t *osd_buffers[MAX_OSD_PARTS];
// this id tells us if the subtitle part has changed or not // this id tells us if the subtitle part has changed or not
int bitmap_pos_id[MAX_OSD_PARTS]; int change_id[MAX_OSD_PARTS];
int64_t recent_flip_time; // last frame event int64_t recent_flip_time; // last frame event
@@ -455,8 +455,8 @@ static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
struct wl_surface *s = p->osd_surfaces[id]; struct wl_surface *s = p->osd_surfaces[id];
if (imgs->bitmap_pos_id != p->bitmap_pos_id[id]) { if (imgs->change_id != p->change_id[id]) {
p->bitmap_pos_id[id] = imgs->bitmap_pos_id; p->change_id[id] = imgs->change_id;
struct mp_rect bb; struct mp_rect bb;
if (!mp_sub_bitmaps_bb(imgs, &bb)) if (!mp_sub_bitmaps_bb(imgs, &bb))