Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2011-2013 Maarten Lankhorst
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice shall be included in
  12.  * all copies or substantial portions of the Software.
  13.  *
  14.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20.  * OTHER DEALINGS IN THE SOFTWARE.
  21.  */
  22.  
  23. #include "nvc0_video.h"
  24.  
  25. struct strparm_bsp {
  26.         uint32_t w0[4]; // bits 0-23 length, bits 24-31 addr_hi
  27.         uint32_t w1[4]; // bit 8-24 addr_lo
  28.         uint32_t unk20; // should be idx * 0x8000000, bitstream offset
  29.         uint32_t do_crypto_crap; // set to 0
  30. };
  31.  
  32. struct mpeg12_picparm_bsp {
  33.         uint16_t width;
  34.         uint16_t height;
  35.         uint8_t picture_structure;
  36.         uint8_t picture_coding_type;
  37.         uint8_t intra_dc_precision;
  38.         uint8_t frame_pred_frame_dct;
  39.         uint8_t concealment_motion_vectors;
  40.         uint8_t intra_vlc_format;
  41.         uint16_t pad;
  42.         uint8_t f_code[2][2];
  43. };
  44.  
  45. struct mpeg4_picparm_bsp {
  46.         uint16_t width;
  47.         uint16_t height;
  48.         uint8_t vop_time_increment_size;
  49.         uint8_t interlaced;
  50.         uint8_t resync_marker_disable;
  51. };
  52.  
  53. struct vc1_picparm_bsp {
  54.         uint16_t width;
  55.         uint16_t height;
  56.         uint8_t profile; // 04 0 simple, 1 main, 2 advanced
  57.         uint8_t postprocflag; // 05
  58.         uint8_t pulldown; // 06
  59.         uint8_t interlaced; // 07
  60.         uint8_t tfcntrflag; // 08
  61.         uint8_t finterpflag; // 09
  62.         uint8_t psf; // 0a
  63.         uint8_t pad; // 0b
  64.         uint8_t multires; // 0c
  65.         uint8_t syncmarker; // 0d
  66.         uint8_t rangered; // 0e
  67.         uint8_t maxbframes; // 0f
  68.         uint8_t dquant; // 10
  69.         uint8_t panscan_flag; // 11
  70.         uint8_t refdist_flag; // 12
  71.         uint8_t quantizer; // 13
  72.         uint8_t extended_mv; // 14
  73.         uint8_t extended_dmv; // 15
  74.         uint8_t overlap; // 16
  75.         uint8_t vstransform; // 17
  76. };
  77.  
  78. struct h264_picparm_bsp {
  79.         // 00
  80.         uint32_t unk00;
  81.         // 04
  82.         uint32_t log2_max_frame_num_minus4; // 04 checked
  83.         uint32_t pic_order_cnt_type; // 08 checked
  84.         uint32_t log2_max_pic_order_cnt_lsb_minus4; // 0c checked
  85.         uint32_t delta_pic_order_always_zero_flag; // 10, or unknown
  86.  
  87.         uint32_t frame_mbs_only_flag; // 14, always 1?
  88.         uint32_t direct_8x8_inference_flag; // 18, always 1?
  89.         uint32_t width_mb; // 1c checked
  90.         uint32_t height_mb; // 20 checked
  91.         // 24
  92.         //struct picparm2
  93.                 uint32_t entropy_coding_mode_flag; // 00, checked
  94.                 uint32_t pic_order_present_flag; // 04 checked
  95.                 uint32_t unk; // 08 seems to be 0?
  96.                 uint32_t pad1; // 0c seems to be 0?
  97.                 uint32_t pad2; // 10 always 0 ?
  98.                 uint32_t num_ref_idx_l0_active_minus1; // 14 always 0?
  99.                 uint32_t num_ref_idx_l1_active_minus1; // 18 always 0?
  100.                 uint32_t weighted_pred_flag; // 1c checked
  101.                 uint32_t weighted_bipred_idc; // 20 checked
  102.                 uint32_t pic_init_qp_minus26; // 24 checked
  103.                 uint32_t deblocking_filter_control_present_flag; // 28 always 1?
  104.                 uint32_t redundant_pic_cnt_present_flag; // 2c always 0?
  105.                 uint32_t transform_8x8_mode_flag; // 30 checked
  106.                 uint32_t mb_adaptive_frame_field_flag; // 34 checked-ish
  107.                 uint8_t field_pic_flag; // 38 checked
  108.                 uint8_t bottom_field_flag; // 39 checked
  109.                 uint8_t real_pad[0x1b]; // XX why?
  110. };
  111.  
  112. static uint32_t
  113. nvc0_decoder_fill_picparm_mpeg12_bsp(struct nvc0_decoder *dec,
  114.                                      struct pipe_mpeg12_picture_desc *desc,
  115.                                      char *map)
  116. {
  117.    struct mpeg12_picparm_bsp *pic_bsp = (struct mpeg12_picparm_bsp *)map;
  118.    int i;
  119.    pic_bsp->width = dec->base.width;
  120.    pic_bsp->height = dec->base.height;
  121.    pic_bsp->picture_structure = desc->picture_structure;
  122.    pic_bsp->picture_coding_type = desc->picture_coding_type;
  123.    pic_bsp->intra_dc_precision = desc->intra_dc_precision;
  124.    pic_bsp->frame_pred_frame_dct = desc->frame_pred_frame_dct;
  125.    pic_bsp->concealment_motion_vectors = desc->concealment_motion_vectors;
  126.    pic_bsp->intra_vlc_format = desc->intra_vlc_format;
  127.    pic_bsp->pad = 0;
  128.    for (i = 0; i < 4; ++i)
  129.       pic_bsp->f_code[i/2][i%2] = desc->f_code[i/2][i%2] + 1; // FU
  130.  
  131.    return (desc->num_slices << 4) | (dec->base.profile != PIPE_VIDEO_PROFILE_MPEG1);
  132. }
  133.  
  134. static uint32_t
  135. nvc0_decoder_fill_picparm_mpeg4_bsp(struct nvc0_decoder *dec,
  136.                                     struct pipe_mpeg4_picture_desc *desc,
  137.                                     char *map)
  138. {
  139.    struct mpeg4_picparm_bsp *pic_bsp = (struct mpeg4_picparm_bsp *)map;
  140.    uint32_t t, bits = 0;
  141.    pic_bsp->width = dec->base.width;
  142.    pic_bsp->height = dec->base.height;
  143.    assert(desc->vop_time_increment_resolution > 0);
  144.  
  145.    t = desc->vop_time_increment_resolution - 1;
  146.    while (t) {
  147.       bits++;
  148.       t /= 2;
  149.    }
  150.    if (!bits)
  151.       bits = 1;
  152.    t = desc->vop_time_increment_resolution - 1;
  153.    pic_bsp->vop_time_increment_size = bits;
  154.    pic_bsp->interlaced = desc->interlaced;
  155.    pic_bsp->resync_marker_disable = desc->resync_marker_disable;
  156.    return 4;
  157. }
  158.  
  159. static uint32_t
  160. nvc0_decoder_fill_picparm_vc1_bsp(struct nvc0_decoder *dec,
  161.                                   struct pipe_vc1_picture_desc *d,
  162.                                   char *map)
  163. {
  164.    struct vc1_picparm_bsp *vc = (struct vc1_picparm_bsp *)map;
  165.    uint32_t caps = (d->slice_count << 4)&0xfff0;
  166.    vc->width = dec->base.width;
  167.    vc->height = dec->base.height;
  168.    vc->profile = dec->base.profile - PIPE_VIDEO_PROFILE_VC1_SIMPLE; // 04
  169.    vc->postprocflag = d->postprocflag;
  170.    vc->pulldown = d->pulldown;
  171.    vc->interlaced = d->interlace;
  172.    vc->tfcntrflag = d->tfcntrflag; // 08
  173.    vc->finterpflag = d->finterpflag;
  174.    vc->psf = d->psf;
  175.    vc->pad = 0;
  176.    vc->multires = d->multires; // 0c
  177.    vc->syncmarker = d->syncmarker;
  178.    vc->rangered = d->rangered;
  179.    vc->maxbframes = d->maxbframes;
  180.    vc->dquant = d->dquant; // 10
  181.    vc->panscan_flag = d->panscan_flag;
  182.    vc->refdist_flag = d->refdist_flag;
  183.    vc->quantizer = d->quantizer;
  184.    vc->extended_mv = d->extended_mv; // 14
  185.    vc->extended_dmv = d->extended_dmv;
  186.    vc->overlap = d->overlap;
  187.    vc->vstransform = d->vstransform;
  188.    return caps | 2;
  189. }
  190.  
  191. static uint32_t
  192. nvc0_decoder_fill_picparm_h264_bsp(struct nvc0_decoder *dec,
  193.                                    struct pipe_h264_picture_desc *d,
  194.                                    char *map)
  195. {
  196.    struct h264_picparm_bsp stub_h = {}, *h = &stub_h;
  197.    uint32_t caps = (d->slice_count << 4)&0xfff0;
  198.  
  199.    assert(!(d->slice_count & ~0xfff));
  200.    if (d->slice_count & 0x1000)
  201.       caps |= 1 << 20;
  202.  
  203.    assert(offsetof(struct h264_picparm_bsp, bottom_field_flag) == (0x39 + 0x24));
  204.    h->unk00 = 1;
  205.    h->pad1 = h->pad2 = 0;
  206.    h->unk = 0;
  207.    h->log2_max_frame_num_minus4 = d->log2_max_frame_num_minus4;
  208.    h->frame_mbs_only_flag = d->frame_mbs_only_flag;
  209.    h->direct_8x8_inference_flag = d->direct_8x8_inference_flag;
  210.    h->width_mb = mb(dec->base.width);
  211.    h->height_mb = mb(dec->base.height);
  212.    h->entropy_coding_mode_flag = d->entropy_coding_mode_flag;
  213.    h->pic_order_present_flag = d->pic_order_present_flag;
  214.    h->pic_order_cnt_type = d->pic_order_cnt_type;
  215.    h->log2_max_pic_order_cnt_lsb_minus4 = d->log2_max_pic_order_cnt_lsb_minus4;
  216.    h->delta_pic_order_always_zero_flag = d->delta_pic_order_always_zero_flag;
  217.    h->num_ref_idx_l0_active_minus1 = d->num_ref_idx_l0_active_minus1;
  218.    h->num_ref_idx_l1_active_minus1 = d->num_ref_idx_l1_active_minus1;
  219.    h->weighted_pred_flag = d->weighted_pred_flag;
  220.    h->weighted_bipred_idc = d->weighted_bipred_idc;
  221.    h->pic_init_qp_minus26 = d->pic_init_qp_minus26;
  222.    h->deblocking_filter_control_present_flag = d->deblocking_filter_control_present_flag;
  223.    h->redundant_pic_cnt_present_flag = d->redundant_pic_cnt_present_flag;
  224.    h->transform_8x8_mode_flag = d->transform_8x8_mode_flag;
  225.    h->mb_adaptive_frame_field_flag = d->mb_adaptive_frame_field_flag;
  226.    h->field_pic_flag = d->field_pic_flag;
  227.    h->bottom_field_flag = d->bottom_field_flag;
  228.    memset(h->real_pad, 0, sizeof(h->real_pad));
  229.    *(struct h264_picparm_bsp *)map = *h;
  230.    return caps | 3;
  231. }
  232.  
  233. #if NVC0_DEBUG_FENCE
  234. static void dump_comm_bsp(struct comm *comm)
  235. {
  236.    unsigned idx = comm->bsp_cur_index & 0xf;
  237.    debug_printf("Cur seq: %x, bsp byte ofs: %x\n", comm->bsp_cur_index, comm->byte_ofs);
  238.    debug_printf("Status: %08x, pos: %08x\n", comm->status[idx], comm->pos[idx]);
  239. }
  240. #endif
  241.  
  242. unsigned
  243. nvc0_decoder_bsp(struct nvc0_decoder *dec, union pipe_desc desc,
  244.                  struct nvc0_video_buffer *target,
  245.                  unsigned comm_seq, unsigned num_buffers,
  246.                  const void *const *data, const unsigned *num_bytes,
  247.                  unsigned *vp_caps, unsigned *is_ref,
  248.                  struct nvc0_video_buffer *refs[16])
  249. {
  250.    struct nouveau_pushbuf *push = dec->pushbuf[0];
  251.    enum pipe_video_codec codec = u_reduce_video_profile(dec->base.profile);
  252.    char *bsp;
  253.    uint32_t bsp_addr, comm_addr, inter_addr;
  254.    uint32_t slice_size, bucket_size, ring_size;
  255.    uint32_t endmarker, caps;
  256.    struct strparm_bsp *str_bsp;
  257.    int ret, i;
  258.    struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NVC0_VIDEO_QDEPTH];
  259.    struct nouveau_bo *inter_bo = dec->inter_bo[comm_seq & 1];
  260.    unsigned fence_extra = 0;
  261.    struct nouveau_pushbuf_refn bo_refs[] = {
  262.       { bsp_bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM },
  263.       { inter_bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM },
  264. #ifdef NVC0_DEBUG_FENCE
  265.       { dec->fence_bo, NOUVEAU_BO_WR | NOUVEAU_BO_GART },
  266. #endif
  267.       { dec->bitplane_bo, NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM },
  268.    };
  269.    int num_refs = sizeof(bo_refs)/sizeof(*bo_refs);
  270.  
  271.    if (!dec->bitplane_bo)
  272.       num_refs--;
  273.  
  274. #ifdef NVC0_DEBUG_FENCE
  275.    fence_extra = 4;
  276. #endif
  277.  
  278.    ret = nouveau_bo_map(bsp_bo, NOUVEAU_BO_WR, dec->client);
  279.    if (ret) {
  280.       debug_printf("map failed: %i %s\n", ret, strerror(-ret));
  281.       return -1;
  282.    }
  283.    bsp = bsp_bo->map;
  284.    /*
  285.     * 0x000..0x100: picparm_bsp
  286.     * 0x200..0x500: picparm_vp
  287.     * 0x500..0x700: comm
  288.     * 0x700..onward: raw bitstream
  289.     */
  290.  
  291.    switch (codec){
  292.    case PIPE_VIDEO_CODEC_MPEG12:
  293.       endmarker = 0xb7010000;
  294.       caps = nvc0_decoder_fill_picparm_mpeg12_bsp(dec, desc.mpeg12, bsp);
  295.       break;
  296.    case PIPE_VIDEO_CODEC_MPEG4:
  297.       endmarker = 0xb1010000;
  298.       caps = nvc0_decoder_fill_picparm_mpeg4_bsp(dec, desc.mpeg4, bsp);
  299.       break;
  300.    case PIPE_VIDEO_CODEC_VC1: {
  301.       endmarker = 0x0a010000;
  302.       caps = nvc0_decoder_fill_picparm_vc1_bsp(dec, desc.vc1, bsp);
  303.       break;
  304.    }
  305.    case PIPE_VIDEO_CODEC_MPEG4_AVC: {
  306.       endmarker = 0x0b010000;
  307.       caps = nvc0_decoder_fill_picparm_h264_bsp(dec, desc.h264, bsp);
  308.       break;
  309.    }
  310.    default: assert(0); return -1;
  311.    }
  312.  
  313.    nvc0_decoder_vp_caps(dec, desc, target, comm_seq, vp_caps, is_ref, refs);
  314.  
  315.    nouveau_pushbuf_space(push, 6 + (codec == PIPE_VIDEO_CODEC_MPEG4_AVC ? 9 : 7) + fence_extra + 2, num_refs, 0);
  316.    nouveau_pushbuf_refn(push, bo_refs, num_refs);
  317.  
  318.    caps |= 0 << 16; // reset struct comm if flag is set
  319.    caps |= 1 << 17; // enable watchdog
  320.    caps |= 0 << 18; // do not report error to VP, so it can continue decoding what we have
  321.    caps |= 0 << 19; // if enabled, use crypto crap?
  322.    bsp += 0x100;
  323.  
  324.    str_bsp = (struct strparm_bsp *)bsp;
  325.    memset(str_bsp, 0, 0x80);
  326.    str_bsp->w0[0] = 16;
  327.    str_bsp->w1[0] = 0x1;
  328.    bsp += 0x100;
  329.    /* Reserved for picparm_vp */
  330.    bsp += 0x300;
  331.    /* Reserved for comm */
  332. #if !NVC0_DEBUG_FENCE
  333.    memset(bsp, 0, 0x200);
  334. #endif
  335.    bsp += 0x200;
  336.    for (i = 0; i < num_buffers; ++i) {
  337.       memcpy(bsp, data[i], num_bytes[i]);
  338.       bsp += num_bytes[i];
  339.       str_bsp->w0[0] += num_bytes[i];
  340.    }
  341.  
  342.    /* Append end sequence */
  343.    *(uint32_t *)bsp = endmarker;
  344.    bsp += 4;
  345.    *(uint32_t *)bsp = 0x00000000;
  346.    bsp += 4;
  347.    *(uint32_t *)bsp = endmarker;
  348.    bsp += 4;
  349.    *(uint32_t *)bsp = 0x00000000;
  350.  
  351.    bsp_addr = bsp_bo->offset >> 8;
  352.    inter_addr = inter_bo->offset >> 8;
  353.  
  354. #if NVC0_DEBUG_FENCE
  355.    memset(dec->comm, 0, 0x200);
  356.    comm_addr = (dec->fence_bo->offset + COMM_OFFSET) >> 8;
  357. #else
  358.    comm_addr = bsp_addr + (COMM_OFFSET>>8);
  359. #endif
  360.  
  361.    BEGIN_NVC0(push, SUBC_BSP(0x700), 5);
  362.    PUSH_DATA (push, caps); // 700 cmd
  363.    PUSH_DATA (push, bsp_addr + 1); // 704 strparm_bsp
  364.    PUSH_DATA (push, bsp_addr + 7); // 708 str addr
  365.    PUSH_DATA (push, comm_addr); // 70c comm
  366.    PUSH_DATA (push, comm_seq); // 710 seq
  367.  
  368.    if (codec != PIPE_VIDEO_CODEC_MPEG4_AVC) {
  369.       u32 bitplane_addr;
  370.  
  371.       bitplane_addr = dec->bitplane_bo->offset >> 8;
  372.  
  373.       nvc0_decoder_inter_sizes(dec, 1, &slice_size, &bucket_size, &ring_size);
  374.       BEGIN_NVC0(push, SUBC_BSP(0x400), 6);
  375.       PUSH_DATA (push, bsp_addr); // 400 picparm addr
  376.       PUSH_DATA (push, inter_addr); // 404 interparm addr
  377.       PUSH_DATA (push, inter_addr + slice_size + bucket_size); // 408 interdata addr
  378.       PUSH_DATA (push, ring_size << 8); // 40c interdata_size
  379.       PUSH_DATA (push, bitplane_addr); // 410 BITPLANE_DATA
  380.       PUSH_DATA (push, 0x400); // 414 BITPLANE_DATA_SIZE
  381.    } else {
  382.       nvc0_decoder_inter_sizes(dec, desc.h264->slice_count, &slice_size, &bucket_size, &ring_size);
  383.       BEGIN_NVC0(push, SUBC_BSP(0x400), 8);
  384.       PUSH_DATA (push, bsp_addr); // 400 picparm addr
  385.       PUSH_DATA (push, inter_addr); // 404 interparm addr
  386.       PUSH_DATA (push, slice_size << 8); // 408 interparm size?
  387.       PUSH_DATA (push, inter_addr + slice_size + bucket_size); // 40c interdata addr
  388.       PUSH_DATA (push, ring_size << 8); // 410 interdata size
  389.       PUSH_DATA (push, inter_addr + slice_size); // 414 bucket?
  390.       PUSH_DATA (push, bucket_size << 8); // 418 bucket size? unshifted..
  391.       PUSH_DATA (push, 0); // 41c targets
  392.       // TODO: Double check 414 / 418 with nvidia trace
  393.    }
  394.  
  395. #if NVC0_DEBUG_FENCE
  396.    BEGIN_NVC0(push, SUBC_BSP(0x240), 3);
  397.    PUSH_DATAh(push, dec->fence_bo->offset);
  398.    PUSH_DATA (push, dec->fence_bo->offset);
  399.    PUSH_DATA (push, dec->fence_seq);
  400.  
  401.    BEGIN_NVC0(push, SUBC_BSP(0x300), 1);
  402.    PUSH_DATA (push, 1);
  403.    PUSH_KICK (push);
  404.  
  405.    {
  406.       unsigned spin = 0;
  407.       do {
  408.          usleep(100);
  409.          if ((spin++ & 0xff) == 0xff) {
  410.             debug_printf("b%u: %u\n", dec->fence_seq, dec->fence_map[0]);
  411.             dump_comm_bsp(dec->comm);
  412.          }
  413.       } while (dec->fence_seq > dec->fence_map[0]);
  414.    }
  415.  
  416.    dump_comm_bsp(dec->comm);
  417.    return dec->comm->status[comm_seq & 0xf];
  418. #else
  419.    BEGIN_NVC0(push, SUBC_BSP(0x300), 1);
  420.    PUSH_DATA (push, 0);
  421.    PUSH_KICK (push);
  422.    return 2;
  423. #endif
  424. }
  425.