nouveau: rework reference frame handling

Fixes a regression from "nouveau/vdec: small fixes to h264 handling"

New picking order for frames:
 1. Vidbuf pointer matches.
 2. Take the first kicked ref.
 3. If that fails, take a ref that has a different last_used.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Cc: "10.2 10.3" <mesa-stable@lists.freedesktop.org>
This commit is contained in:
Maarten Lankhorst 2014-09-10 13:20:53 +02:00 committed by Ilia Mirkin
parent 121ceb38f4
commit a41aad8431
3 changed files with 37 additions and 4 deletions

View file

@ -196,11 +196,15 @@ nouveau_vp3_handle_references(struct nouveau_vp3_decoder *dec, struct nouveau_vp
/* Try to find a real empty spot first, there should be one..
*/
for (i = 0; i < dec->base.max_references + 1; ++i) {
if (dec->refs[i].last_used != seq) {
if (dec->refs[i].vidbuf == target) {
empty_spot = i;
break;
}
} else if (!dec->refs[i].last_used) {
empty_spot = i;
} else if (empty_spot == ~0U && dec->refs[i].last_used != seq)
empty_spot = i;
}
assert(empty_spot < dec->base.max_references+1);
dec->refs[empty_spot].last_used = seq;
// debug_printf("Kicked %p to add %p to slot %i\n", dec->refs[empty_spot].vidbuf, target, empty_spot);
@ -463,14 +467,45 @@ void nouveau_vp3_vp_caps(struct nouveau_vp3_decoder *dec, union pipe_desc desc,
case PIPE_VIDEO_FORMAT_MPEG12:
*caps = nouveau_vp3_fill_picparm_mpeg12_vp(dec, desc.mpeg12, refs, is_ref, vp);
nouveau_vp3_handle_references(dec, refs, dec->fence_seq, target);
switch (desc.mpeg12->picture_structure) {
case PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_TOP:
dec->refs[target->valid_ref].decoded_top = 1;
break;
case PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_BOTTOM:
dec->refs[target->valid_ref].decoded_bottom = 1;
break;
default:
dec->refs[target->valid_ref].decoded_top = 1;
dec->refs[target->valid_ref].decoded_bottom = 1;
break;
}
return;
case PIPE_VIDEO_FORMAT_MPEG4:
*caps = nouveau_vp3_fill_picparm_mpeg4_vp(dec, desc.mpeg4, refs, is_ref, vp);
nouveau_vp3_handle_references(dec, refs, dec->fence_seq, target);
// XXX: Correct?
if (!desc.mpeg4->interlaced) {
dec->refs[target->valid_ref].decoded_top = 1;
dec->refs[target->valid_ref].decoded_bottom = 1;
} else if (desc.mpeg4->top_field_first) {
if (!dec->refs[target->valid_ref].decoded_top)
dec->refs[target->valid_ref].decoded_top = 1;
else
dec->refs[target->valid_ref].decoded_bottom = 1;
} else {
if (!dec->refs[target->valid_ref].decoded_bottom)
dec->refs[target->valid_ref].decoded_bottom = 1;
else
dec->refs[target->valid_ref].decoded_top = 1;
}
return;
case PIPE_VIDEO_FORMAT_VC1: {
*caps = nouveau_vp3_fill_picparm_vc1_vp(dec, desc.vc1, refs, is_ref, vp);
nouveau_vp3_handle_references(dec, refs, dec->fence_seq, target);
if (desc.vc1->frame_coding_mode == 3)
debug_printf("Field-Interlaced possibly incorrectly handled\n");
dec->refs[target->valid_ref].decoded_top = 1;
dec->refs[target->valid_ref].decoded_bottom = 1;
return;
}
case PIPE_VIDEO_FORMAT_MPEG4_AVC: {

View file

@ -59,7 +59,6 @@ static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32
static void
nv98_decoder_kick_ref(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video_buffer *target)
{
dec->refs[target->valid_ref].vidbuf = NULL;
dec->refs[target->valid_ref].last_used = 0;
// debug_printf("Unreffed %p\n", target);
}

View file

@ -59,7 +59,6 @@ static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32
static void
nvc0_decoder_kick_ref(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video_buffer *target)
{
dec->refs[target->valid_ref].vidbuf = NULL;
dec->refs[target->valid_ref].last_used = 0;
// debug_printf("Unreffed %p\n", target);
}