vl: Add support for max level query v2
[mesa.git] / src / gallium / drivers / radeon / radeon_uvd.c
index dfd1d9f7246ffed850617c4a0d111f1213dee63e..e3c3dd63d4f0c88dccaf5d8b54c596da0c14dadd 100644 (file)
@@ -514,6 +514,7 @@ static uint32_t get_ref_pic_idx(struct ruvd_decoder *dec, struct pipe_video_buff
 static struct ruvd_mpeg2 get_mpeg2_msg(struct ruvd_decoder *dec,
                                       struct pipe_mpeg12_picture_desc *pic)
 {
+       const int *zscan = pic->alternate_scan ? vl_zscan_alternate : vl_zscan_normal;
        struct ruvd_mpeg2 result;
        unsigned i;
 
@@ -524,8 +525,11 @@ static struct ruvd_mpeg2 get_mpeg2_msg(struct ruvd_decoder *dec,
 
        result.load_intra_quantiser_matrix = 1;
        result.load_nonintra_quantiser_matrix = 1;
-       memcpy(&result.intra_quantiser_matrix, pic->intra_matrix, 64);
-       memcpy(&result.nonintra_quantiser_matrix, pic->non_intra_matrix, 64);
+
+       for (i = 0; i < 64; ++i) {
+               result.intra_quantiser_matrix[i] = pic->intra_matrix[zscan[i]];
+               result.nonintra_quantiser_matrix[i] = pic->non_intra_matrix[zscan[i]];
+       }
 
        result.profile_and_level_indication = 0;
        result.chroma_format = 0x1;
@@ -553,16 +557,22 @@ static struct ruvd_mpeg4 get_mpeg4_msg(struct ruvd_decoder *dec,
 {
        struct ruvd_mpeg4 result;
        unsigned i;
+
        memset(&result, 0, sizeof(result));
        result.decoded_pic_idx = dec->frame_number;
        for (i = 0; i < 2; ++i)
                result.ref_pic_idx[i] = get_ref_pic_idx(dec, pic->ref[i]);
 
+       result.variant_type = 0;
+       result.profile_and_level_indication = 0xF0; // ASP Level0
+
+       result.video_object_layer_verid = 0x5; // advanced simple
+       result.video_object_layer_shape = 0x0; // rectangular
+
        result.video_object_layer_width = dec->base.width;
-        result.video_object_layer_height = dec->base.height;
+       result.video_object_layer_height = dec->base.height;
 
        result.vop_time_increment_resolution = pic->vop_time_increment_resolution;
-       result.quant_type = pic->quant_type;
 
        result.flags |= pic->short_video_header << 0;
        //result.flags |= obmc_disable << 1;
@@ -570,19 +580,23 @@ static struct ruvd_mpeg4 get_mpeg4_msg(struct ruvd_decoder *dec,
         result.flags |= 1 << 3; // load_intra_quant_mat
        result.flags |= 1 << 4; // load_nonintra_quant_mat
        result.flags |= pic->quarter_sample << 5;
-       //result.flags |= complexity_estimation_disable << 6
+       result.flags |= 1 << 6; // complexity_estimation_disable
        result.flags |= pic->resync_marker_disable << 7;
        //result.flags |= data_partitioned << 8;
        //result.flags |= reversible_vlc << 9;
-       //result.flags |= newpred_enable << 10;
-       //result.flags |= reduced_resolution_vop_enable << 11;
+       result.flags |= 0 << 10; // newpred_enable
+       result.flags |= 0 << 11; // reduced_resolution_vop_enable
        //result.flags |= scalability << 12;
        //result.flags |= is_object_layer_identifier << 13;
        //result.flags |= fixed_vop_rate << 14;
        //result.flags |= newpred_segment_type << 15;
 
-       memcpy(&result.intra_quant_mat, pic->intra_matrix, 64);
-       memcpy(&result.nonintra_quant_mat, pic->non_intra_matrix, 64);
+       result.quant_type = pic->quant_type;
+
+       for (i = 0; i < 64; ++i) {
+               result.intra_quant_mat[i] = pic->intra_matrix[vl_zscan_normal[i]];
+               result.nonintra_quant_mat[i] = pic->non_intra_matrix[vl_zscan_normal[i]];
+       }
 
        /*
        int32_t         trd [2]
@@ -744,31 +758,31 @@ static void ruvd_end_frame(struct pipe_video_decoder *decoder,
        msg.stream_handle = dec->stream_handle;
        msg.status_report_feedback_number = dec->frame_number;
 
-       msg.decode.stream_type = profile2stream_type(dec->base.profile);
-       msg.decode.decode_flags = 0x1;
-       msg.decode.width_in_samples = dec->base.width;
-       msg.decode.height_in_samples = dec->base.height;
+       msg.body.decode.stream_type = profile2stream_type(dec->base.profile);
+       msg.body.decode.decode_flags = 0x1;
+       msg.body.decode.width_in_samples = dec->base.width;
+       msg.body.decode.height_in_samples = dec->base.height;
 
-       msg.decode.dpb_size = dec->dpb.buf->size;
-       msg.decode.bsd_size = bs_size;
+       msg.body.decode.dpb_size = dec->dpb.buf->size;
+       msg.body.decode.bsd_size = bs_size;
 
        dt = dec->set_dtb(&msg, (struct vl_video_buffer *)target);
 
        switch (u_reduce_video_profile(picture->profile)) {
        case PIPE_VIDEO_CODEC_MPEG4_AVC:
-               msg.decode.h264 = get_h264_msg(dec, (struct pipe_h264_picture_desc*)picture);
+               msg.body.decode.codec.h264 = get_h264_msg(dec, (struct pipe_h264_picture_desc*)picture);
                break;
 
        case PIPE_VIDEO_CODEC_VC1:
-               msg.decode.vc1 = get_vc1_msg((struct pipe_vc1_picture_desc*)picture);
+               msg.body.decode.codec.vc1 = get_vc1_msg((struct pipe_vc1_picture_desc*)picture);
                break;
 
        case PIPE_VIDEO_CODEC_MPEG12:
-               msg.decode.mpeg2 = get_mpeg2_msg(dec, (struct pipe_mpeg12_picture_desc*)picture);
+               msg.body.decode.codec.mpeg2 = get_mpeg2_msg(dec, (struct pipe_mpeg12_picture_desc*)picture);
                break;
 
        case PIPE_VIDEO_CODEC_MPEG4:
-               msg.decode.mpeg4 = get_mpeg4_msg(dec, (struct pipe_mpeg4_picture_desc*)picture);
+               msg.body.decode.codec.mpeg4 = get_mpeg4_msg(dec, (struct pipe_mpeg4_picture_desc*)picture);
                break;
 
        default:
@@ -776,8 +790,8 @@ static void ruvd_end_frame(struct pipe_video_decoder *decoder,
                return;
        }
 
-       msg.decode.db_surf_tile_config = msg.decode.dt_surf_tile_config;
-       msg.decode.extension_support = 0x1;
+       msg.body.decode.db_surf_tile_config = msg.body.decode.dt_surf_tile_config;
+       msg.body.decode.extension_support = 0x1;
 
        send_msg(dec, &msg);
        send_cmd(dec, RUVD_CMD_DPB_BUFFER, dec->dpb.cs_handle, 0,
@@ -814,13 +828,16 @@ struct pipe_video_decoder *ruvd_create_decoder(struct pipe_context *context,
                                               ruvd_set_dtb set_dtb)
 {
        unsigned dpb_size = calc_dpb_size(profile, width, height, max_references);
+       struct radeon_info info;
        struct ruvd_decoder *dec;
        struct ruvd_msg msg;
        int i;
 
+       ws->query_info(ws, &info);
+
        switch(u_reduce_video_profile(profile)) {
        case PIPE_VIDEO_CODEC_MPEG12:
-               if (entrypoint > PIPE_VIDEO_ENTRYPOINT_BITSTREAM)
+               if (entrypoint > PIPE_VIDEO_ENTRYPOINT_BITSTREAM || info.family < CHIP_PALM)
                        return vl_create_mpeg12_decoder(context, profile, entrypoint,
                                                        chroma_format, width,
                                                        height, max_references, expect_chunked_decode);
@@ -892,10 +909,10 @@ struct pipe_video_decoder *ruvd_create_decoder(struct pipe_context *context,
        msg.size = sizeof(msg);
        msg.msg_type = RUVD_MSG_CREATE;
        msg.stream_handle = dec->stream_handle;
-       msg.create.stream_type = profile2stream_type(dec->base.profile);
-       msg.create.width_in_samples = dec->base.width;
-       msg.create.height_in_samples = dec->base.height;
-       msg.create.dpb_size = dec->dpb.buf->size;
+       msg.body.create.stream_type = profile2stream_type(dec->base.profile);
+       msg.body.create.width_in_samples = dec->base.width;
+       msg.body.create.height_in_samples = dec->base.height;
+       msg.body.create.dpb_size = dec->dpb.buf->size;
        send_msg(dec, &msg);
        flush(dec);
        next_buffer(dec);
@@ -1029,42 +1046,42 @@ static unsigned bank_wh(unsigned bankwh)
 void ruvd_set_dt_surfaces(struct ruvd_msg *msg, struct radeon_surface *luma,
                          struct radeon_surface *chroma)
 {
-       msg->decode.dt_pitch = luma->level[0].pitch_bytes;
+       msg->body.decode.dt_pitch = luma->level[0].pitch_bytes;
        switch (luma->level[0].mode) {
        case RADEON_SURF_MODE_LINEAR_ALIGNED:
-               msg->decode.dt_tiling_mode = RUVD_TILE_LINEAR;
-               msg->decode.dt_array_mode = RUVD_ARRAY_MODE_LINEAR;
+               msg->body.decode.dt_tiling_mode = RUVD_TILE_LINEAR;
+               msg->body.decode.dt_array_mode = RUVD_ARRAY_MODE_LINEAR;
                break;
        case RADEON_SURF_MODE_1D:
-               msg->decode.dt_tiling_mode = RUVD_TILE_8X8;
-               msg->decode.dt_array_mode = RUVD_ARRAY_MODE_1D_THIN;
+               msg->body.decode.dt_tiling_mode = RUVD_TILE_8X8;
+               msg->body.decode.dt_array_mode = RUVD_ARRAY_MODE_1D_THIN;
                break;
        case RADEON_SURF_MODE_2D:
-               msg->decode.dt_tiling_mode = RUVD_TILE_8X8;
-               msg->decode.dt_array_mode = RUVD_ARRAY_MODE_2D_THIN;
+               msg->body.decode.dt_tiling_mode = RUVD_TILE_8X8;
+               msg->body.decode.dt_array_mode = RUVD_ARRAY_MODE_2D_THIN;
                break;
        default:
                assert(0);
                break;
        }
 
-       msg->decode.dt_luma_top_offset = texture_offset(luma, 0);
-       msg->decode.dt_chroma_top_offset = texture_offset(chroma, 0);
-       if (msg->decode.dt_field_mode) {
-               msg->decode.dt_luma_bottom_offset = texture_offset(luma, 1);
-               msg->decode.dt_chroma_bottom_offset = texture_offset(chroma, 1);
+       msg->body.decode.dt_luma_top_offset = texture_offset(luma, 0);
+       msg->body.decode.dt_chroma_top_offset = texture_offset(chroma, 0);
+       if (msg->body.decode.dt_field_mode) {
+               msg->body.decode.dt_luma_bottom_offset = texture_offset(luma, 1);
+               msg->body.decode.dt_chroma_bottom_offset = texture_offset(chroma, 1);
        } else {
-               msg->decode.dt_luma_bottom_offset = msg->decode.dt_luma_top_offset;
-               msg->decode.dt_chroma_bottom_offset = msg->decode.dt_chroma_top_offset;
+               msg->body.decode.dt_luma_bottom_offset = msg->body.decode.dt_luma_top_offset;
+               msg->body.decode.dt_chroma_bottom_offset = msg->body.decode.dt_chroma_top_offset;
        }
 
        assert(luma->bankw == chroma->bankw);
        assert(luma->bankh == chroma->bankh);
        assert(luma->mtilea == chroma->mtilea);
 
-       msg->decode.dt_surf_tile_config |= RUVD_BANK_WIDTH(bank_wh(luma->bankw));
-       msg->decode.dt_surf_tile_config |= RUVD_BANK_HEIGHT(bank_wh(luma->bankh));
-       msg->decode.dt_surf_tile_config |= RUVD_MACRO_TILE_ASPECT_RATIO(macro_tile_aspect(luma->mtilea));
+       msg->body.decode.dt_surf_tile_config |= RUVD_BANK_WIDTH(bank_wh(luma->bankw));
+       msg->body.decode.dt_surf_tile_config |= RUVD_BANK_HEIGHT(bank_wh(luma->bankh));
+       msg->body.decode.dt_surf_tile_config |= RUVD_MACRO_TILE_ASPECT_RATIO(macro_tile_aspect(luma->mtilea));
 }
 
 int ruvd_get_video_param(struct pipe_screen *screen,
@@ -1076,7 +1093,6 @@ int ruvd_get_video_param(struct pipe_screen *screen,
                switch (u_reduce_video_profile(profile)) {
                case PIPE_VIDEO_CODEC_MPEG12:
                case PIPE_VIDEO_CODEC_MPEG4:
-                       /* TODO not all hw families support MPEG4 */
                case PIPE_VIDEO_CODEC_MPEG4_AVC:
                case PIPE_VIDEO_CODEC_VC1:
                        return true;
@@ -1092,11 +1108,35 @@ int ruvd_get_video_param(struct pipe_screen *screen,
        case PIPE_VIDEO_CAP_PREFERED_FORMAT:
                return PIPE_FORMAT_NV12;
        case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
-               return false;
+               return true;
        case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
-               return false; /* TODO: enable this */
+               return true;
        case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
                return true;
+       case PIPE_VIDEO_CAP_MAX_LEVEL:
+               switch (profile) {
+               case PIPE_VIDEO_PROFILE_MPEG1:
+                       return 0;
+               case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
+               case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
+                       return 3;
+               case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE:
+                       return 3;
+               case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE:
+                       return 5;
+               case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
+                       return 1;
+               case PIPE_VIDEO_PROFILE_VC1_MAIN:
+                       return 2;
+               case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
+                       return 4;
+               case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
+               case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
+               case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
+                       return 41;
+               default:
+                       return 0;
+               }
        default:
                return 0;
        }