"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/nouveau/nv50/nv98_video.c" (16 Sep 2020, 10996 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "nv98_video.c" see the Fossies "Dox" file reference documentation.

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