@@ -45,6 +45,7 @@ struct SpuColour {
guint16 U;
guint16 V;
guint8 A;
+ guint8 vis; /* is this color visible? */
};
void gstspu_clear_comp_buffers (SpuState * state);
@@ -258,7 +258,7 @@ pgs_composition_object_render (PgsCompositionObject * obj, SpuState * state,
}
colour = &state->pgs.palette[pal_id];
- if (colour->A) {
+ if (colour->A && colour->vis) {
guint32 inv_A = 0xff - colour->A;
if (G_UNLIKELY (x + run_len > max_x))
run_len = (max_x - x);
@@ -492,6 +492,8 @@ parse_set_palette (GstDVDSpu * dvdspu, guint8 type, guint8 * payload,
state->pgs.palette[n].U = U * A;
state->pgs.palette[n].V = V * A;
state->pgs.palette[n].A = A;
+ state->pgs.palette[n].vis = state->pgs.palette[n].Y ||
+ state->pgs.palette[n].U || state->pgs.palette[n].V;
payload += PGS_PALETTE_ENTRY_SIZE;
}
@@ -47,6 +47,7 @@ gstspu_vobsub_recalc_palette (GstDVDSpu * dvdspu,
/* U/V are stored as V/U in the clut words, so switch them */
dest->V = ((guint16) ((col >> 8) & 0xff)) * dest->A;
dest->U = ((guint16) (col & 0xff)) * dest->A;
+ dest->vis = dest->Y || dest->V || dest->U;
}
} else {
int y = 240;
@@ -168,7 +169,7 @@ gstspu_vobsub_get_rle_code (SpuState * state, guint16 * rle_offset)
return code;
}
-static inline void
+static inline gboolean
gstspu_vobsub_draw_rle_run (SpuState * state, gint16 x, gint16 end,
SpuColour * colour)
{
@@ -177,7 +178,7 @@ gstspu_vobsub_draw_rle_run (SpuState * state, gint16 x, gint16 end,
state->vobsub.cur_Y, x, end, colour->Y, colour->U, colour->V, colour->A);
#endif
- if (colour->A != 0) {
+ if ((colour->A != 0) && colour->vis) {
guint32 inv_A = 0xff - colour->A;
/* FIXME: This could be more efficient */
@@ -191,7 +192,10 @@ gstspu_vobsub_draw_rle_run (SpuState * state, gint16 x, gint16 end,
}
/* Update the compositing buffer so we know how much to blend later */
*(state->vobsub.comp_last_x_ptr) = end - 1; /* end is the start of the *next* run */
+
+ return TRUE;
}
+ return FALSE;
}
static inline gint16
@@ -204,16 +208,17 @@ rle_end_x (guint16 rle_code, gint16 x, gint16 end)
return MIN (end, x + (rle_code >> 2));
}
-static void gstspu_vobsub_render_line_with_chgcol (SpuState * state,
+static gboolean gstspu_vobsub_render_line_with_chgcol (SpuState * state,
guint8 * planes[3], guint16 * rle_offset);
static gboolean gstspu_vobsub_update_chgcol (SpuState * state);
-static void
+static gboolean
gstspu_vobsub_render_line (SpuState * state, guint8 * planes[3],
guint16 * rle_offset)
{
gint16 x, next_x, end, rle_code, next_draw_x;
SpuColour *colour;
+ gboolean visible = FALSE;
/* Check for special case of chg_col info to use (either highlight or
* ChgCol command */
@@ -222,8 +227,7 @@ gstspu_vobsub_render_line (SpuState * state, guint8 * planes[3],
/* Check the top & bottom, because we might not be within the region yet */
if (state->vobsub.cur_Y >= state->vobsub.cur_chg_col->top &&
state->vobsub.cur_Y <= state->vobsub.cur_chg_col->bottom) {
- gstspu_vobsub_render_line_with_chgcol (state, planes, rle_offset);
- return;
+ return gstspu_vobsub_render_line_with_chgcol (state, planes, rle_offset);
}
}
}
@@ -248,9 +252,11 @@ gstspu_vobsub_render_line (SpuState * state, guint8 * planes[3],
if (next_draw_x > state->vobsub.clip_rect.right)
next_draw_x = state->vobsub.clip_rect.right; /* ensure no overflow */
/* Now draw the run between [x,next_x) */
- gstspu_vobsub_draw_rle_run (state, x, next_draw_x, colour);
+ visible |= gstspu_vobsub_draw_rle_run (state, x, next_draw_x, colour);
x = next_x;
}
+
+ return visible;
}
static gboolean
@@ -280,7 +286,7 @@ gstspu_vobsub_update_chgcol (SpuState * state)
return FALSE;
}
-static void
+static gboolean
gstspu_vobsub_render_line_with_chgcol (SpuState * state, guint8 * planes[3],
guint16 * rle_offset)
{
@@ -292,6 +298,7 @@ gstspu_vobsub_render_line_with_chgcol (SpuState * state, guint8 * planes[3],
SpuVobsubPixCtrlI *next_pix_ctrl;
SpuVobsubPixCtrlI *end_pix_ctrl;
SpuVobsubPixCtrlI dummy_pix_ctrl;
+ gboolean visible = FALSE;
gint16 cur_reg_end;
gint i;
@@ -340,7 +347,7 @@ gstspu_vobsub_render_line_with_chgcol (SpuState * state, guint8 * planes[3],
if (G_LIKELY (x < run_end)) {
colour = &cur_pix_ctrl->pal_cache[rle_code & 3];
- gstspu_vobsub_draw_rle_run (state, x, run_draw_end, colour);
+ visible |= gstspu_vobsub_draw_rle_run (state, x, run_draw_end, colour);
x = run_end;
}
@@ -356,6 +363,8 @@ gstspu_vobsub_render_line_with_chgcol (SpuState * state, guint8 * planes[3],
}
}
}
+
+ return visible;
}
static void
@@ -510,7 +519,7 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
for (state->vobsub.cur_Y = y; state->vobsub.cur_Y <= last_y;
state->vobsub.cur_Y++) {
- gboolean clip;
+ gboolean clip, visible = FALSE;
clip = (state->vobsub.cur_Y < state->vobsub.clip_rect.top
|| state->vobsub.cur_Y > state->vobsub.clip_rect.bottom);
@@ -519,7 +528,7 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
gstspu_vobsub_clear_comp_buffers (state);
/* Render even line */
state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x;
- gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]);
+ visible |= gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]);
if (!clip) {
/* Advance the luminance output pointer */
planes[0] += state->Y_stride;
@@ -528,9 +537,9 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
/* Render odd line */
state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x + 1;
- gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[1]);
+ visible |= gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[1]);
- if (!clip) {
+ if (visible && !clip) {
/* Blend the accumulated UV compositing buffers onto the output */
gstspu_vobsub_blend_comp_buffers (state, planes);
@@ -541,7 +550,7 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
}
}
if (state->vobsub.cur_Y == state->vobsub.disp_rect.bottom) {
- gboolean clip;
+ gboolean clip, visible = FALSE;
clip = (state->vobsub.cur_Y < state->vobsub.clip_rect.top
|| state->vobsub.cur_Y > state->vobsub.clip_rect.bottom);
@@ -553,8 +562,9 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf)
* after the above loop exited. */
gstspu_vobsub_clear_comp_buffers (state);
state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x;
- gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]);
- gstspu_vobsub_blend_comp_buffers (state, planes);
+ visible |= gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]);
+ if (visible)
+ gstspu_vobsub_blend_comp_buffers (state, planes);
}
}