"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/nouveau/nouveau_vp3_video.c" (16 Sep 2020, 16310 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 "nouveau_vp3_video.c" see the Fossies "Dox" file reference documentation.

    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 <sys/mman.h>
   24 #include <sys/stat.h>
   25 #include <stdio.h>
   26 #include <fcntl.h>
   27 
   28 #include <nvif/class.h>
   29 
   30 #include "nouveau_screen.h"
   31 #include "nouveau_context.h"
   32 #include "nouveau_vp3_video.h"
   33 
   34 #include "util/u_video.h"
   35 #include "util/format/u_format.h"
   36 #include "util/u_sampler.h"
   37 
   38 static struct pipe_sampler_view **
   39 nouveau_vp3_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
   40 {
   41    struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
   42    return buf->sampler_view_planes;
   43 }
   44 
   45 static struct pipe_sampler_view **
   46 nouveau_vp3_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
   47 {
   48    struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
   49    return buf->sampler_view_components;
   50 }
   51 
   52 static struct pipe_surface **
   53 nouveau_vp3_video_buffer_surfaces(struct pipe_video_buffer *buffer)
   54 {
   55    struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
   56    return buf->surfaces;
   57 }
   58 
   59 static void
   60 nouveau_vp3_video_buffer_destroy(struct pipe_video_buffer *buffer)
   61 {
   62    struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
   63    unsigned i;
   64 
   65    assert(buf);
   66 
   67    for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
   68       pipe_resource_reference(&buf->resources[i], NULL);
   69       pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
   70       pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
   71       pipe_surface_reference(&buf->surfaces[i * 2], NULL);
   72       pipe_surface_reference(&buf->surfaces[i * 2 + 1], NULL);
   73    }
   74    FREE(buffer);
   75 }
   76 
   77 struct pipe_video_buffer *
   78 nouveau_vp3_video_buffer_create(struct pipe_context *pipe,
   79                          const struct pipe_video_buffer *templat,
   80                          int flags)
   81 {
   82    struct nouveau_vp3_video_buffer *buffer;
   83    struct pipe_resource templ;
   84    unsigned i, j, component;
   85    struct pipe_sampler_view sv_templ;
   86    struct pipe_surface surf_templ;
   87 
   88    if (getenv("XVMC_VL") || templat->buffer_format != PIPE_FORMAT_NV12)
   89       return vl_video_buffer_create(pipe, templat);
   90 
   91    assert(templat->interlaced);
   92    assert(pipe_format_to_chroma_format(templat->buffer_format) == PIPE_VIDEO_CHROMA_FORMAT_420);
   93 
   94    buffer = CALLOC_STRUCT(nouveau_vp3_video_buffer);
   95    if (!buffer)
   96       return NULL;
   97 
   98    buffer->base.buffer_format = templat->buffer_format;
   99    buffer->base.context = pipe;
  100    buffer->base.destroy = nouveau_vp3_video_buffer_destroy;
  101    buffer->base.width = templat->width;
  102    buffer->base.height = templat->height;
  103    buffer->base.get_sampler_view_planes = nouveau_vp3_video_buffer_sampler_view_planes;
  104    buffer->base.get_sampler_view_components = nouveau_vp3_video_buffer_sampler_view_components;
  105    buffer->base.get_surfaces = nouveau_vp3_video_buffer_surfaces;
  106    buffer->base.interlaced = true;
  107 
  108    memset(&templ, 0, sizeof(templ));
  109    templ.target = PIPE_TEXTURE_2D_ARRAY;
  110    templ.depth0 = 1;
  111    templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
  112    templ.format = PIPE_FORMAT_R8_UNORM;
  113    templ.width0 = buffer->base.width;
  114    templ.height0 = (buffer->base.height + 1)/2;
  115    templ.flags = flags;
  116    templ.array_size = 2;
  117 
  118    buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ);
  119    if (!buffer->resources[0])
  120       goto error;
  121 
  122    templ.format = PIPE_FORMAT_R8G8_UNORM;
  123    buffer->num_planes = 2;
  124    templ.width0 = (templ.width0 + 1) / 2;
  125    templ.height0 = (templ.height0 + 1) / 2;
  126    for (i = 1; i < buffer->num_planes; ++i) {
  127       buffer->resources[i] = pipe->screen->resource_create(pipe->screen, &templ);
  128       if (!buffer->resources[i])
  129          goto error;
  130    }
  131 
  132    memset(&sv_templ, 0, sizeof(sv_templ));
  133    for (component = 0, i = 0; i < buffer->num_planes; ++i ) {
  134       struct pipe_resource *res = buffer->resources[i];
  135       unsigned nr_components = util_format_get_nr_components(res->format);
  136 
  137       u_sampler_view_default_template(&sv_templ, res, res->format);
  138       buffer->sampler_view_planes[i] = pipe->create_sampler_view(pipe, res, &sv_templ);
  139       if (!buffer->sampler_view_planes[i])
  140          goto error;
  141 
  142       for (j = 0; j < nr_components; ++j, ++component) {
  143          sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_X + j;
  144          sv_templ.swizzle_a = PIPE_SWIZZLE_1;
  145 
  146          buffer->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
  147          if (!buffer->sampler_view_components[component])
  148             goto error;
  149       }
  150   }
  151 
  152    memset(&surf_templ, 0, sizeof(surf_templ));
  153    for (j = 0; j < buffer->num_planes; ++j) {
  154       surf_templ.format = buffer->resources[j]->format;
  155       surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 0;
  156       buffer->surfaces[j * 2] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
  157       if (!buffer->surfaces[j * 2])
  158          goto error;
  159 
  160       surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 1;
  161       buffer->surfaces[j * 2 + 1] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
  162       if (!buffer->surfaces[j * 2 + 1])
  163          goto error;
  164    }
  165 
  166    return &buffer->base;
  167 
  168 error:
  169    nouveau_vp3_video_buffer_destroy(&buffer->base);
  170    return NULL;
  171 }
  172 
  173 static void
  174 nouveau_vp3_decoder_flush(struct pipe_video_codec *decoder)
  175 {
  176 }
  177 
  178 static void
  179 nouveau_vp3_decoder_begin_frame(struct pipe_video_codec *decoder,
  180                                 struct pipe_video_buffer *target,
  181                                 struct pipe_picture_desc *picture)
  182 {
  183 }
  184 
  185 static void
  186 nouveau_vp3_decoder_end_frame(struct pipe_video_codec *decoder,
  187                               struct pipe_video_buffer *target,
  188                               struct pipe_picture_desc *picture)
  189 {
  190 }
  191 
  192 static void
  193 nouveau_vp3_decoder_destroy(struct pipe_video_codec *decoder)
  194 {
  195    struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
  196    int i;
  197 
  198    nouveau_bo_ref(NULL, &dec->ref_bo);
  199    nouveau_bo_ref(NULL, &dec->bitplane_bo);
  200    nouveau_bo_ref(NULL, &dec->inter_bo[0]);
  201    nouveau_bo_ref(NULL, &dec->inter_bo[1]);
  202 #if NOUVEAU_VP3_DEBUG_FENCE
  203    nouveau_bo_ref(NULL, &dec->fence_bo);
  204 #endif
  205    nouveau_bo_ref(NULL, &dec->fw_bo);
  206 
  207    for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH; ++i)
  208       nouveau_bo_ref(NULL, &dec->bsp_bo[i]);
  209 
  210    nouveau_object_del(&dec->bsp);
  211    nouveau_object_del(&dec->vp);
  212    nouveau_object_del(&dec->ppp);
  213 
  214    if (dec->channel[0] != dec->channel[1]) {
  215       for (i = 0; i < 3; ++i) {
  216          nouveau_pushbuf_del(&dec->pushbuf[i]);
  217          nouveau_object_del(&dec->channel[i]);
  218       }
  219    } else {
  220       nouveau_pushbuf_del(dec->pushbuf);
  221       nouveau_object_del(dec->channel);
  222    }
  223 
  224    FREE(dec);
  225 }
  226 
  227 void
  228 nouveau_vp3_decoder_init_common(struct pipe_video_codec *dec)
  229 {
  230    dec->destroy = nouveau_vp3_decoder_destroy;
  231    dec->flush = nouveau_vp3_decoder_flush;
  232    dec->begin_frame = nouveau_vp3_decoder_begin_frame;
  233    dec->end_frame = nouveau_vp3_decoder_end_frame;
  234 }
  235 
  236 static void vp3_getpath(enum pipe_video_profile profile, char *path)
  237 {
  238    switch (u_reduce_video_profile(profile)) {
  239       case PIPE_VIDEO_FORMAT_MPEG12: {
  240          sprintf(path, "/lib/firmware/nouveau/vuc-vp3-mpeg12-0");
  241          break;
  242       }
  243       case PIPE_VIDEO_FORMAT_VC1: {
  244          sprintf(path, "/lib/firmware/nouveau/vuc-vp3-vc1-0");
  245          break;
  246       }
  247       case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
  248          sprintf(path, "/lib/firmware/nouveau/vuc-vp3-h264-0");
  249          break;
  250       }
  251       default: assert(0);
  252    }
  253 }
  254 
  255 static void vp4_getpath(enum pipe_video_profile profile, char *path)
  256 {
  257    switch (u_reduce_video_profile(profile)) {
  258       case PIPE_VIDEO_FORMAT_MPEG12: {
  259          sprintf(path, "/lib/firmware/nouveau/vuc-mpeg12-0");
  260          break;
  261       }
  262       case PIPE_VIDEO_FORMAT_MPEG4: {
  263          sprintf(path, "/lib/firmware/nouveau/vuc-mpeg4-0");
  264          break;
  265       }
  266       case PIPE_VIDEO_FORMAT_VC1: {
  267          sprintf(path, "/lib/firmware/nouveau/vuc-vc1-0");
  268          break;
  269       }
  270       case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
  271          sprintf(path, "/lib/firmware/nouveau/vuc-h264-0");
  272          break;
  273       }
  274       default: assert(0);
  275    }
  276 }
  277 
  278 int
  279 nouveau_vp3_load_firmware(struct nouveau_vp3_decoder *dec,
  280                           enum pipe_video_profile profile,
  281                           unsigned chipset)
  282 {
  283    int fd;
  284    char path[PATH_MAX];
  285    ssize_t r;
  286    uint32_t *end, endval;
  287 
  288    if (chipset >= 0xa3 && chipset != 0xaa && chipset != 0xac)
  289       vp4_getpath(profile, path);
  290    else
  291       vp3_getpath(profile, path);
  292 
  293    if (nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client))
  294       return 1;
  295 
  296    fd = open(path, O_RDONLY | O_CLOEXEC);
  297    if (fd < 0) {
  298       fprintf(stderr, "opening firmware file %s failed: %m\n", path);
  299       return 1;
  300    }
  301    r = read(fd, dec->fw_bo->map, 0x4000);
  302    close(fd);
  303 
  304    if (r < 0) {
  305       fprintf(stderr, "reading firmware file %s failed: %m\n", path);
  306       return 1;
  307    }
  308 
  309    if (r == 0x4000) {
  310       fprintf(stderr, "firmware file %s too large!\n", path);
  311       return 1;
  312    }
  313 
  314    if (r & 0xff) {
  315       fprintf(stderr, "firmware file %s wrong size!\n", path);
  316       return 1;
  317    }
  318 
  319    end = dec->fw_bo->map + r - 4;
  320    endval = *end;
  321    while (endval == *end)
  322       end--;
  323 
  324    r = (intptr_t)end - (intptr_t)dec->fw_bo->map + 4;
  325 
  326    switch (u_reduce_video_profile(profile)) {
  327       case PIPE_VIDEO_FORMAT_MPEG12: {
  328          assert((r & 0xff) == 0xe0);
  329          dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
  330          break;
  331       }
  332       case PIPE_VIDEO_FORMAT_MPEG4: {
  333          assert((r & 0xff) == 0xe0);
  334          dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
  335          break;
  336       }
  337       case PIPE_VIDEO_FORMAT_VC1: {
  338          assert((r & 0xff) == 0xac);
  339          dec->fw_sizes = (0x3ac<<16) | (r - 0x3ac);
  340          break;
  341       }
  342       case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
  343          assert((r & 0xff) == 0x70);
  344          dec->fw_sizes = (0x370<<16) | (r - 0x370);
  345          break;
  346       }
  347       default:
  348          return 1;
  349    }
  350    munmap(dec->fw_bo->map, dec->fw_bo->size);
  351    dec->fw_bo->map = NULL;
  352    return 0;
  353 }
  354 
  355 static const struct nouveau_mclass
  356 nouveau_decoder_msvld[] = {
  357    { G98_MSVLD, -1 },
  358    { IGT21A_MSVLD, -1 },
  359    { GT212_MSVLD, -1 },
  360    { GF100_MSVLD, -1 },
  361    { GK104_MSVLD, -1 },
  362    {}
  363 };
  364 
  365 static int
  366 firmware_present(struct pipe_screen *pscreen, enum pipe_video_profile profile)
  367 {
  368    struct nouveau_screen *screen = nouveau_screen(pscreen);
  369    int chipset = screen->device->chipset;
  370    int vp3 = chipset < 0xa3 || chipset == 0xaa || chipset == 0xac;
  371    int vp5 = chipset >= 0xd0;
  372    int ret;
  373 
  374    /* For all chipsets, try to create a BSP objects. Assume that if firmware
  375     * is present for it, firmware is also present for VP/PPP */
  376    if (!(screen->firmware_info.profiles_checked & 1)) {
  377       struct nouveau_object *channel = NULL, *bsp = NULL;
  378       struct nv04_fifo nv04_data = {.vram = 0xbeef0201, .gart = 0xbeef0202};
  379       struct nvc0_fifo nvc0_args = {};
  380       struct nve0_fifo nve0_args = {.engine = NVE0_FIFO_ENGINE_BSP};
  381       void *data = NULL;
  382       int size;
  383 
  384       if (chipset < 0xc0) {
  385          data = &nv04_data;
  386          size = sizeof(nv04_data);
  387       } else if (chipset < 0xe0) {
  388          data = &nvc0_args;
  389          size = sizeof(nvc0_args);
  390       } else {
  391          data = &nve0_args;
  392          size = sizeof(nve0_args);
  393       }
  394 
  395       /* kepler must have its own channel, so just do this for everyone */
  396       nouveau_object_new(&screen->device->object, 0,
  397                          NOUVEAU_FIFO_CHANNEL_CLASS,
  398                          data, size, &channel);
  399 
  400       if (channel) {
  401          ret = nouveau_object_mclass(channel, nouveau_decoder_msvld);
  402          if (ret >= 0)
  403             nouveau_object_new(channel, 0, nouveau_decoder_msvld[ret].oclass,
  404                                NULL, 0, &bsp);
  405          if (bsp)
  406             screen->firmware_info.profiles_present |= 1;
  407          nouveau_object_del(&bsp);
  408          nouveau_object_del(&channel);
  409       }
  410       screen->firmware_info.profiles_checked |= 1;
  411    }
  412 
  413    if (!(screen->firmware_info.profiles_present & 1))
  414       return 0;
  415 
  416    /* For vp3/vp4 chipsets, make sure that the relevant firmware is present */
  417    if (!vp5 && !(screen->firmware_info.profiles_checked & (1 << profile))) {
  418       char path[PATH_MAX];
  419       struct stat s;
  420       if (vp3)
  421          vp3_getpath(profile, path);
  422       else
  423          vp4_getpath(profile, path);
  424       ret = stat(path, &s);
  425       if (!ret && s.st_size > 1000)
  426          screen->firmware_info.profiles_present |= (1 << profile);
  427       screen->firmware_info.profiles_checked |= (1 << profile);
  428    }
  429 
  430    return vp5 || (screen->firmware_info.profiles_present & (1 << profile));
  431 }
  432 
  433 int
  434 nouveau_vp3_screen_get_video_param(struct pipe_screen *pscreen,
  435                                    enum pipe_video_profile profile,
  436                                    enum pipe_video_entrypoint entrypoint,
  437                                    enum pipe_video_cap param)
  438 {
  439    int chipset = nouveau_screen(pscreen)->device->chipset;
  440    int vp3 = chipset < 0xa3 || chipset == 0xaa || chipset == 0xac;
  441    int vp5 = chipset >= 0xd0;
  442    enum pipe_video_format codec = u_reduce_video_profile(profile);
  443    switch (param) {
  444    case PIPE_VIDEO_CAP_SUPPORTED:
  445       /* VP3 does not support MPEG4, VP4+ do. */
  446       return entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM &&
  447          profile >= PIPE_VIDEO_PROFILE_MPEG1 &&
  448          profile < PIPE_VIDEO_PROFILE_HEVC_MAIN &&
  449          (!vp3 || codec != PIPE_VIDEO_FORMAT_MPEG4) &&
  450          firmware_present(pscreen, profile);
  451    case PIPE_VIDEO_CAP_NPOT_TEXTURES:
  452       return 1;
  453    case PIPE_VIDEO_CAP_MAX_WIDTH:
  454    case PIPE_VIDEO_CAP_MAX_HEIGHT:
  455       return vp5 ? 4096 : 2048;
  456    case PIPE_VIDEO_CAP_PREFERED_FORMAT:
  457       return PIPE_FORMAT_NV12;
  458    case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
  459    case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
  460       return true;
  461    case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
  462       return false;
  463    case PIPE_VIDEO_CAP_MAX_LEVEL:
  464       switch (profile) {
  465       case PIPE_VIDEO_PROFILE_MPEG1:
  466          return 0;
  467       case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
  468       case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
  469          return 3;
  470       case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE:
  471          return 3;
  472       case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE:
  473          return 5;
  474       case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
  475          return 1;
  476       case PIPE_VIDEO_PROFILE_VC1_MAIN:
  477          return 2;
  478       case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
  479          return 4;
  480       case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
  481       case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
  482       case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
  483          return 41;
  484       default:
  485          debug_printf("unknown video profile: %d\n", profile);
  486          return 0;
  487       }
  488    default:
  489       debug_printf("unknown video param: %d\n", param);
  490       return 0;
  491    }
  492 }
  493 
  494 bool
  495 nouveau_vp3_screen_video_supported(struct pipe_screen *screen,
  496                                    enum pipe_format format,
  497                                    enum pipe_video_profile profile,
  498                                    enum pipe_video_entrypoint entrypoint)
  499 {
  500    if (profile != PIPE_VIDEO_PROFILE_UNKNOWN)
  501       return format == PIPE_FORMAT_NV12;
  502 
  503    return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint);
  504 }