Home | History | Annotate | Download | only in nvc0
      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/nvc0_video.h"
     24 
     25 #include "util/u_sampler.h"
     26 #include "util/u_format.h"
     27 
     28 static void
     29 nvc0_decoder_begin_frame(struct pipe_video_codec *decoder,
     30                          struct pipe_video_buffer *target,
     31                          struct pipe_picture_desc *picture)
     32 {
     33    struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
     34    uint32_t comm_seq = ++dec->fence_seq;
     35    MAYBE_UNUSED unsigned ret = 0; /* used in debug checks */
     36 
     37    assert(dec);
     38    assert(target);
     39    assert(target->buffer_format == PIPE_FORMAT_NV12);
     40 
     41    ret = nvc0_decoder_bsp_begin(dec, comm_seq);
     42 
     43    assert(ret == 2);
     44 }
     45 
     46 static void
     47 nvc0_decoder_decode_bitstream(struct pipe_video_codec *decoder,
     48                               struct pipe_video_buffer *video_target,
     49                               struct pipe_picture_desc *picture,
     50                               unsigned num_buffers,
     51                               const void *const *data,
     52                               const unsigned *num_bytes)
     53 {
     54    struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
     55    uint32_t comm_seq = dec->fence_seq;
     56    MAYBE_UNUSED unsigned ret = 0; /* used in debug checks */
     57 
     58    assert(decoder);
     59 
     60    ret = nvc0_decoder_bsp_next(dec, comm_seq, num_buffers, data, num_bytes);
     61 
     62    assert(ret == 2);
     63 }
     64 
     65 static void
     66 nvc0_decoder_end_frame(struct pipe_video_codec *decoder,
     67                        struct pipe_video_buffer *video_target,
     68                        struct pipe_picture_desc *picture)
     69 {
     70    struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
     71    struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target;
     72    uint32_t comm_seq = dec->fence_seq;
     73    union pipe_desc desc;
     74 
     75    unsigned vp_caps, is_ref;
     76    MAYBE_UNUSED unsigned ret; /* used in debug checks */
     77    struct nouveau_vp3_video_buffer *refs[16] = {};
     78 
     79    desc.base = picture;
     80 
     81    ret = nvc0_decoder_bsp_end(dec, desc, target, comm_seq, &vp_caps, &is_ref, refs);
     82 
     83    /* did we decode bitstream correctly? */
     84    assert(ret == 2);
     85 
     86    nvc0_decoder_vp(dec, desc, target, comm_seq, vp_caps, is_ref, refs);
     87    nvc0_decoder_ppp(dec, desc, target, comm_seq);
     88 }
     89 
     90 struct pipe_video_codec *
     91 nvc0_create_decoder(struct pipe_context *context,
     92                     const struct pipe_video_codec *templ)
     93 {
     94    struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base;
     95    struct nouveau_vp3_decoder *dec;
     96    struct nouveau_pushbuf **push;
     97    union nouveau_bo_config cfg;
     98    bool kepler = screen->device->chipset >= 0xe0;
     99 
    100    cfg.nvc0.tile_mode = 0x10;
    101    cfg.nvc0.memtype = 0xfe;
    102 
    103    int ret, i;
    104    uint32_t codec = 1, ppp_codec = 3;
    105    uint32_t timeout;
    106    u32 tmp_size = 0;
    107 
    108    if (getenv("XVMC_VL"))
    109        return vl_create_decoder(context, templ);
    110 
    111    if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
    112       debug_printf("%x\n", templ->entrypoint);
    113       return NULL;
    114    }
    115 
    116    dec = CALLOC_STRUCT(nouveau_vp3_decoder);
    117    if (!dec)
    118       return NULL;
    119    dec->client = screen->client;
    120    dec->base = *templ;
    121    nouveau_vp3_decoder_init_common(&dec->base);
    122 
    123    if (!kepler) {
    124       dec->bsp_idx = 5;
    125       dec->vp_idx = 6;
    126       dec->ppp_idx = 7;
    127    } else {
    128       dec->bsp_idx = 2;
    129       dec->vp_idx = 2;
    130       dec->ppp_idx = 2;
    131    }
    132 
    133    for (i = 0; i < 3; ++i)
    134       if (i && !kepler) {
    135          dec->channel[i] = dec->channel[0];
    136          dec->pushbuf[i] = dec->pushbuf[0];
    137       } else {
    138          void *data;
    139          u32 size;
    140          struct nvc0_fifo nvc0_args = {};
    141          struct nve0_fifo nve0_args = {};
    142 
    143          if (!kepler) {
    144             size = sizeof(nvc0_args);
    145             data = &nvc0_args;
    146          } else {
    147             unsigned engine[] = {
    148                NVE0_FIFO_ENGINE_BSP,
    149                NVE0_FIFO_ENGINE_VP,
    150                NVE0_FIFO_ENGINE_PPP
    151             };
    152 
    153             nve0_args.engine = engine[i];
    154             size = sizeof(nve0_args);
    155             data = &nve0_args;
    156          }
    157 
    158          ret = nouveau_object_new(&screen->device->object, 0,
    159                                   NOUVEAU_FIFO_CHANNEL_CLASS,
    160                                   data, size, &dec->channel[i]);
    161 
    162          if (!ret)
    163             ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4,
    164                                    32 * 1024, true, &dec->pushbuf[i]);
    165          if (ret)
    166             break;
    167       }
    168    push = dec->pushbuf;
    169 
    170    if (!kepler) {
    171       if (!ret)
    172          ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp);
    173       if (!ret)
    174          ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp);
    175       if (!ret)
    176          ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp);
    177    } else {
    178       if (!ret)
    179          ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp);
    180       if (!ret)
    181          ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp);
    182       if (!ret)
    183          ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp);
    184    }
    185    if (ret)
    186       goto fail;
    187 
    188    BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
    189    PUSH_DATA (push[0], dec->bsp->handle);
    190 
    191    BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
    192    PUSH_DATA (push[1], dec->vp->handle);
    193 
    194    BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
    195    PUSH_DATA (push[2], dec->ppp->handle);
    196 
    197    dec->base.context = context;
    198    dec->base.begin_frame = nvc0_decoder_begin_frame;
    199    dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
    200    dec->base.end_frame = nvc0_decoder_end_frame;
    201 
    202    for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
    203       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
    204                            0, 1 << 20, &cfg, &dec->bsp_bo[i]);
    205    if (!ret) {
    206       /* total fudge factor... just has to be bigger for higher bitrates? */
    207       unsigned inter_size = align(templ->width * templ->height * 2, 4 << 20);
    208       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
    209                            0x100, inter_size, &cfg, &dec->inter_bo[0]);
    210    }
    211    if (!ret) {
    212       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
    213                            0x100, dec->inter_bo[0]->size, &cfg,
    214                            &dec->inter_bo[1]);
    215    }
    216    if (ret)
    217       goto fail;
    218    switch (u_reduce_video_profile(templ->profile)) {
    219    case PIPE_VIDEO_FORMAT_MPEG12: {
    220       codec = 1;
    221       assert(templ->max_references <= 2);
    222       break;
    223    }
    224    case PIPE_VIDEO_FORMAT_MPEG4: {
    225       codec = 4;
    226       tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
    227       assert(templ->max_references <= 2);
    228       break;
    229    }
    230    case PIPE_VIDEO_FORMAT_VC1: {
    231       ppp_codec = codec = 2;
    232       tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
    233       assert(templ->max_references <= 2);
    234       break;
    235    }
    236    case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
    237       codec = 3;
    238       dec->tmp_stride = 16 * mb_half(templ->width) * nouveau_vp3_video_align(templ->height) * 3 / 2;
    239       tmp_size = dec->tmp_stride * (templ->max_references + 1);
    240       assert(templ->max_references <= 16);
    241       break;
    242    }
    243    default:
    244       fprintf(stderr, "invalid codec\n");
    245       goto fail;
    246    }
    247 
    248    if (screen->device->chipset < 0xd0) {
    249       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
    250                            0x4000, &cfg, &dec->fw_bo);
    251       if (ret)
    252          goto fail;
    253 
    254       ret = nouveau_vp3_load_firmware(dec, templ->profile, screen->device->chipset);
    255       if (ret)
    256          goto fw_fail;
    257    }
    258 
    259    if (codec != 3) {
    260       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
    261                            0x400, &cfg, &dec->bitplane_bo);
    262       if (ret)
    263          goto fail;
    264    }
    265 
    266    dec->ref_stride = mb(templ->width)*16 * (mb_half(templ->height)*32 + nouveau_vp3_video_align(templ->height)/2);
    267    ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
    268                         dec->ref_stride * (templ->max_references+2) + tmp_size,
    269                         &cfg, &dec->ref_bo);
    270    if (ret)
    271       goto fail;
    272 
    273    timeout = 0;
    274 
    275    BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2);
    276    PUSH_DATA (push[0], codec);
    277    PUSH_DATA (push[0], timeout);
    278 
    279    BEGIN_NVC0(push[1], SUBC_VP(0x200), 2);
    280    PUSH_DATA (push[1], codec);
    281    PUSH_DATA (push[1], timeout);
    282 
    283    BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2);
    284    PUSH_DATA (push[2], ppp_codec);
    285    PUSH_DATA (push[2], timeout);
    286 
    287    ++dec->fence_seq;
    288 
    289 #if NOUVEAU_VP3_DEBUG_FENCE
    290    ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
    291                         0, 0x1000, NULL, &dec->fence_bo);
    292    if (ret)
    293       goto fail;
    294 
    295    nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
    296    dec->fence_map = dec->fence_bo->map;
    297    dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
    298    dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
    299 
    300    /* So lets test if the fence is working? */
    301    nouveau_pushbuf_space(push[0], 16, 1, 0);
    302    PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
    303    BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
    304    PUSH_DATAh(push[0], dec->fence_bo->offset);
    305    PUSH_DATA (push[0], dec->fence_bo->offset);
    306    PUSH_DATA (push[0], dec->fence_seq);
    307 
    308    BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
    309    PUSH_DATA (push[0], 0);
    310    PUSH_KICK (push[0]);
    311 
    312    nouveau_pushbuf_space(push[1], 16, 1, 0);
    313    PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
    314    BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
    315    PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
    316    PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
    317    PUSH_DATA (push[1], dec->fence_seq);
    318 
    319    BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
    320    PUSH_DATA (push[1], 0);
    321    PUSH_KICK (push[1]);
    322 
    323    nouveau_pushbuf_space(push[2], 16, 1, 0);
    324    PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
    325    BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
    326    PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
    327    PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
    328    PUSH_DATA (push[2], dec->fence_seq);
    329 
    330    BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
    331    PUSH_DATA (push[2], 0);
    332    PUSH_KICK (push[2]);
    333 
    334    usleep(100);
    335    while (dec->fence_seq > dec->fence_map[0] ||
    336           dec->fence_seq > dec->fence_map[4] ||
    337           dec->fence_seq > dec->fence_map[8]) {
    338       debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
    339       usleep(100);
    340    }
    341    debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
    342 #endif
    343 
    344    return &dec->base;
    345 
    346 fw_fail:
    347    debug_printf("Cannot create decoder without firmware..\n");
    348    dec->base.destroy(&dec->base);
    349    return NULL;
    350 
    351 fail:
    352    debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
    353    dec->base.destroy(&dec->base);
    354    return NULL;
    355 }
    356 
    357 struct pipe_video_buffer *
    358 nvc0_video_buffer_create(struct pipe_context *pipe,
    359                          const struct pipe_video_buffer *templat)
    360 {
    361    return nouveau_vp3_video_buffer_create(
    362          pipe, templat, NVC0_RESOURCE_FLAG_VIDEO);
    363 }
    364