Subversion Repositories Kolibri OS

Rev

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