Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2013 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 <sys/mman.h>
  24. #include <sys/stat.h>
  25. #include <sys/types.h>
  26. #include <fcntl.h>
  27.  
  28. #include "util/u_format.h"
  29. #include "util/u_sampler.h"
  30. #include "vl/vl_zscan.h"
  31.  
  32. #include "nv84_video.h"
  33.  
  34. static int
  35. nv84_copy_firmware(const char *path, void *dest, ssize_t len)
  36. {
  37.    int fd = open(path, O_RDONLY | O_CLOEXEC);
  38.    ssize_t r;
  39.    if (fd < 0) {
  40.       fprintf(stderr, "opening firmware file %s failed: %m\n", path);
  41.       return 1;
  42.    }
  43.    r = read(fd, dest, len);
  44.    close(fd);
  45.  
  46.    if (r != len) {
  47.       fprintf(stderr, "reading firwmare file %s failed: %m\n", path);
  48.       return 1;
  49.    }
  50.  
  51.    return 0;
  52. }
  53.  
  54. static int
  55. filesize(const char *path)
  56. {
  57.    int ret;
  58.    struct stat statbuf;
  59.  
  60.    ret = stat(path, &statbuf);
  61.    if (ret)
  62.       return ret;
  63.    return statbuf.st_size;
  64. }
  65.  
  66. static struct nouveau_bo *
  67. nv84_load_firmwares(struct nouveau_device *dev, struct nv84_decoder *dec,
  68.                     const char *fw1, const char *fw2)
  69. {
  70.    int ret, size1, size2 = 0;
  71.    struct nouveau_bo *fw;
  72.  
  73.    size1 = filesize(fw1);
  74.    if (fw2)
  75.       size2 = filesize(fw2);
  76.    if (size1 < 0 || size2 < 0)
  77.       return NULL;
  78.  
  79.    dec->vp_fw2_offset = align(size1, 0x100);
  80.  
  81.    ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, dec->vp_fw2_offset + size2, NULL, &fw);
  82.    if (ret)
  83.       return NULL;
  84.    ret = nouveau_bo_map(fw, NOUVEAU_BO_WR, dec->client);
  85.    if (ret)
  86.       goto error;
  87.  
  88.    ret = nv84_copy_firmware(fw1, fw->map, size1);
  89.    if (fw2 && !ret)
  90.       ret = nv84_copy_firmware(fw2, fw->map + dec->vp_fw2_offset, size2);
  91.    munmap(fw->map, fw->size);
  92.    fw->map = NULL;
  93.    if (!ret)
  94.       return fw;
  95. error:
  96.    nouveau_bo_ref(NULL, &fw);
  97.    return NULL;
  98. }
  99.  
  100. static struct nouveau_bo *
  101. nv84_load_bsp_firmware(struct nouveau_device *dev, struct nv84_decoder *dec)
  102. {
  103.    return nv84_load_firmwares(
  104.          dev, dec, "/lib/firmware/nouveau/nv84_bsp-h264", NULL);
  105. }
  106.  
  107. static struct nouveau_bo *
  108. nv84_load_vp_firmware(struct nouveau_device *dev, struct nv84_decoder *dec)
  109. {
  110.    return nv84_load_firmwares(
  111.          dev, dec,
  112.          "/lib/firmware/nouveau/nv84_vp-h264-1",
  113.          "/lib/firmware/nouveau/nv84_vp-h264-2");
  114. }
  115.  
  116. static struct nouveau_bo *
  117. nv84_load_vp_firmware_mpeg(struct nouveau_device *dev, struct nv84_decoder *dec)
  118. {
  119.    return nv84_load_firmwares(
  120.          dev, dec, "/lib/firmware/nouveau/nv84_vp-mpeg12", NULL);
  121. }
  122.  
  123. static void
  124. nv84_decoder_decode_bitstream_h264(struct pipe_video_decoder *decoder,
  125.                                    struct pipe_video_buffer *video_target,
  126.                                    struct pipe_picture_desc *picture,
  127.                                    unsigned num_buffers,
  128.                                    const void *const *data,
  129.                                    const unsigned *num_bytes)
  130. {
  131.    struct nv84_decoder *dec = (struct nv84_decoder *)decoder;
  132.    struct nv84_video_buffer *target = (struct nv84_video_buffer *)video_target;
  133.  
  134.    struct pipe_h264_picture_desc *desc = (struct pipe_h264_picture_desc *)picture;
  135.  
  136.    assert(target->base.buffer_format == PIPE_FORMAT_NV12);
  137.  
  138.    nv84_decoder_bsp(dec, desc, num_buffers, data, num_bytes, target);
  139.    nv84_decoder_vp_h264(dec, desc, target);
  140. }
  141.  
  142. static void
  143. nv84_decoder_flush(struct pipe_video_decoder *decoder)
  144. {
  145. }
  146.  
  147. static void
  148. nv84_decoder_begin_frame_h264(struct pipe_video_decoder *decoder,
  149.                               struct pipe_video_buffer *target,
  150.                               struct pipe_picture_desc *picture)
  151. {
  152. }
  153.  
  154. static void
  155. nv84_decoder_end_frame_h264(struct pipe_video_decoder *decoder,
  156.                             struct pipe_video_buffer *target,
  157.                             struct pipe_picture_desc *picture)
  158. {
  159. }
  160.  
  161. static void
  162. nv84_decoder_decode_bitstream_mpeg12(struct pipe_video_decoder *decoder,
  163.                                      struct pipe_video_buffer *video_target,
  164.                                      struct pipe_picture_desc *picture,
  165.                                      unsigned num_buffers,
  166.                                      const void *const *data,
  167.                                      const unsigned *num_bytes)
  168. {
  169.    struct nv84_decoder *dec = (struct nv84_decoder *)decoder;
  170.  
  171.    assert(video_target->buffer_format == PIPE_FORMAT_NV12);
  172.  
  173.    vl_mpg12_bs_decode(dec->mpeg12_bs,
  174.                       video_target,
  175.                       (struct pipe_mpeg12_picture_desc *)picture,
  176.                       num_buffers,
  177.                       data,
  178.                       num_bytes);
  179. }
  180.  
  181. static void
  182. nv84_decoder_begin_frame_mpeg12(struct pipe_video_decoder *decoder,
  183.                               struct pipe_video_buffer *target,
  184.                               struct pipe_picture_desc *picture)
  185. {
  186.    struct nv84_decoder *dec = (struct nv84_decoder *)decoder;
  187.    struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture;
  188.    int i;
  189.  
  190.    nouveau_bo_wait(dec->mpeg12_bo, NOUVEAU_BO_RDWR, dec->client);
  191.    dec->mpeg12_mb_info = dec->mpeg12_bo->map + 0x100;
  192.    dec->mpeg12_data = dec->mpeg12_bo->map + 0x100 +
  193.       align(0x20 * mb(dec->base.width) * mb(dec->base.height), 0x100);
  194.    if (desc->intra_matrix) {
  195.       dec->zscan = desc->alternate_scan ? vl_zscan_alternate : vl_zscan_normal;
  196.       for (i = 0; i < 64; i++) {
  197.          dec->mpeg12_intra_matrix[i] = desc->intra_matrix[dec->zscan[i]];
  198.          dec->mpeg12_non_intra_matrix[i] = desc->non_intra_matrix[dec->zscan[i]];
  199.       }
  200.       dec->mpeg12_intra_matrix[0] = 1 << (7 - desc->intra_dc_precision);
  201.    }
  202. }
  203.  
  204. static void
  205. nv84_decoder_end_frame_mpeg12(struct pipe_video_decoder *decoder,
  206.                               struct pipe_video_buffer *target,
  207.                               struct pipe_picture_desc *picture)
  208. {
  209.    nv84_decoder_vp_mpeg12(
  210.          (struct nv84_decoder *)decoder,
  211.          (struct pipe_mpeg12_picture_desc *)picture,
  212.          (struct nv84_video_buffer *)target);
  213. }
  214.  
  215. static void
  216. nv84_decoder_decode_macroblock(struct pipe_video_decoder *decoder,
  217.                                struct pipe_video_buffer *target,
  218.                                struct pipe_picture_desc *picture,
  219.                                const struct pipe_macroblock *macroblocks,
  220.                                unsigned num_macroblocks)
  221. {
  222.    const struct pipe_mpeg12_macroblock *mb = (const struct pipe_mpeg12_macroblock *)macroblocks;
  223.    for (int i = 0; i < num_macroblocks; i++, mb++) {
  224.       nv84_decoder_vp_mpeg12_mb(
  225.             (struct nv84_decoder *)decoder,
  226.             (struct pipe_mpeg12_picture_desc *)picture,
  227.             mb);
  228.    }
  229. }
  230.  
  231. static void
  232. nv84_decoder_destroy(struct pipe_video_decoder *decoder)
  233. {
  234.    struct nv84_decoder *dec = (struct nv84_decoder *)decoder;
  235.  
  236.    nouveau_bo_ref(NULL, &dec->bsp_fw);
  237.    nouveau_bo_ref(NULL, &dec->bsp_data);
  238.    nouveau_bo_ref(NULL, &dec->vp_fw);
  239.    nouveau_bo_ref(NULL, &dec->vp_data);
  240.    nouveau_bo_ref(NULL, &dec->mbring);
  241.    nouveau_bo_ref(NULL, &dec->vpring);
  242.    nouveau_bo_ref(NULL, &dec->bitstream);
  243.    nouveau_bo_ref(NULL, &dec->vp_params);
  244.    nouveau_bo_ref(NULL, &dec->fence);
  245.  
  246.    nouveau_object_del(&dec->bsp);
  247.    nouveau_object_del(&dec->vp);
  248.  
  249.    nouveau_bufctx_del(&dec->bsp_bufctx);
  250.    nouveau_pushbuf_del(&dec->bsp_pushbuf);
  251.    nouveau_object_del(&dec->bsp_channel);
  252.  
  253.    nouveau_bufctx_del(&dec->vp_bufctx);
  254.    nouveau_pushbuf_del(&dec->vp_pushbuf);
  255.    nouveau_object_del(&dec->vp_channel);
  256.  
  257.    nouveau_client_del(&dec->client);
  258.  
  259.    if (dec->mpeg12_bs)
  260.       FREE(dec->mpeg12_bs);
  261.    FREE(dec);
  262. }
  263.  
  264. struct pipe_video_decoder *
  265. nv84_create_decoder(struct pipe_context *context,
  266.                     enum pipe_video_profile profile,
  267.                     enum pipe_video_entrypoint entrypoint,
  268.                     enum pipe_video_chroma_format chroma_format,
  269.                     unsigned width, unsigned height,
  270.                     unsigned max_references,
  271.                     bool chunked_decode)
  272. {
  273.    struct nv50_context *nv50 = (struct nv50_context *)context;
  274.    struct nouveau_screen *screen = &nv50->screen->base;
  275.    struct nv84_decoder *dec;
  276.    struct nouveau_pushbuf *bsp_push, *vp_push;
  277.    struct nv50_surface surf;
  278.    struct nv50_miptree mip;
  279.    union pipe_color_union color;
  280.    struct nv04_fifo nv04_data = { .vram = 0xbeef0201, .gart = 0xbeef0202 };
  281.    int ret, i;
  282.    int is_h264 = u_reduce_video_profile(profile) == PIPE_VIDEO_CODEC_MPEG4_AVC;
  283.    int is_mpeg12 = u_reduce_video_profile(profile) == PIPE_VIDEO_CODEC_MPEG12;
  284.  
  285.    if (getenv("XVMC_VL"))
  286.       return vl_create_decoder(context, profile, entrypoint,
  287.                                chroma_format, width, height,
  288.                                max_references, chunked_decode);
  289.  
  290.    if ((is_h264 && entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) ||
  291.        (is_mpeg12 && entrypoint > PIPE_VIDEO_ENTRYPOINT_IDCT)) {
  292.       debug_printf("%x\n", entrypoint);
  293.       return NULL;
  294.    }
  295.  
  296.    if (!is_h264 && !is_mpeg12) {
  297.       debug_printf("invalid profile: %x\n", profile);
  298.       return NULL;
  299.    }
  300.  
  301.    dec = CALLOC_STRUCT(nv84_decoder);
  302.    if (!dec)
  303.       return NULL;
  304.  
  305.    dec->base.context = context;
  306.    dec->base.profile = profile;
  307.    dec->base.entrypoint = entrypoint;
  308.    dec->base.chroma_format = chroma_format;
  309.    dec->base.width = width;
  310.    dec->base.height = height;
  311.    dec->base.max_references = max_references;
  312.    dec->base.destroy = nv84_decoder_destroy;
  313.    dec->base.flush = nv84_decoder_flush;
  314.    if (is_h264) {
  315.       dec->base.decode_bitstream = nv84_decoder_decode_bitstream_h264;
  316.       dec->base.begin_frame = nv84_decoder_begin_frame_h264;
  317.       dec->base.end_frame = nv84_decoder_end_frame_h264;
  318.  
  319.       dec->frame_mbs = mb(dec->base.width) * mb_half(dec->base.height) * 2;
  320.       dec->frame_size = dec->frame_mbs << 8;
  321.       dec->vpring_deblock = align(0x30 * dec->frame_mbs, 0x100);
  322.       dec->vpring_residual = 0x2000 + MAX2(0x32000, 0x600 * dec->frame_mbs);
  323.       dec->vpring_ctrl = MAX2(0x10000, align(0x1080 + 0x144 * dec->frame_mbs, 0x100));
  324.    } else if (is_mpeg12) {
  325.       dec->base.decode_macroblock = nv84_decoder_decode_macroblock;
  326.       dec->base.begin_frame = nv84_decoder_begin_frame_mpeg12;
  327.       dec->base.end_frame = nv84_decoder_end_frame_mpeg12;
  328.  
  329.       if (entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
  330.          dec->mpeg12_bs = CALLOC_STRUCT(vl_mpg12_bs);
  331.          if (!dec->mpeg12_bs)
  332.             goto fail;
  333.          vl_mpg12_bs_init(dec->mpeg12_bs, &dec->base);
  334.          dec->base.decode_bitstream = nv84_decoder_decode_bitstream_mpeg12;
  335.       }
  336.    } else {
  337.       goto fail;
  338.    }
  339.  
  340.    ret = nouveau_client_new(screen->device, &dec->client);
  341.    if (ret)
  342.       goto fail;
  343.  
  344.    if (is_h264) {
  345.       ret = nouveau_object_new(&screen->device->object, 0,
  346.                                NOUVEAU_FIFO_CHANNEL_CLASS,
  347.                                &nv04_data, sizeof(nv04_data), &dec->bsp_channel);
  348.       if (ret)
  349.          goto fail;
  350.  
  351.       ret = nouveau_pushbuf_new(dec->client, dec->bsp_channel, 4,
  352.                                 32 * 1024, true, &dec->bsp_pushbuf);
  353.       if (ret)
  354.          goto fail;
  355.  
  356.       ret = nouveau_bufctx_new(dec->client, 1, &dec->bsp_bufctx);
  357.       if (ret)
  358.          goto fail;
  359.    }
  360.  
  361.    ret = nouveau_object_new(&screen->device->object, 0,
  362.                             NOUVEAU_FIFO_CHANNEL_CLASS,
  363.                             &nv04_data, sizeof(nv04_data), &dec->vp_channel);
  364.    if (ret)
  365.       goto fail;
  366.    ret = nouveau_pushbuf_new(dec->client, dec->vp_channel, 4,
  367.                              32 * 1024, true, &dec->vp_pushbuf);
  368.    if (ret)
  369.       goto fail;
  370.  
  371.    ret = nouveau_bufctx_new(dec->client, 1, &dec->vp_bufctx);
  372.    if (ret)
  373.       goto fail;
  374.  
  375.    bsp_push = dec->bsp_pushbuf;
  376.    vp_push = dec->vp_pushbuf;
  377.  
  378.    if (is_h264) {
  379.       dec->bsp_fw = nv84_load_bsp_firmware(screen->device, dec);
  380.       dec->vp_fw = nv84_load_vp_firmware(screen->device, dec);
  381.       if (!dec->bsp_fw || !dec->vp_fw)
  382.          goto fail;
  383.    }
  384.    if (is_mpeg12) {
  385.       dec->vp_fw = nv84_load_vp_firmware_mpeg(screen->device, dec);
  386.       if (!dec->vp_fw)
  387.          goto fail;
  388.    }
  389.  
  390.    if (is_h264) {
  391.       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP,
  392.                            0, 0x40000, NULL, &dec->bsp_data);
  393.       if (ret)
  394.          goto fail;
  395.    }
  396.    ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP,
  397.                         0, 0x40000, NULL, &dec->vp_data);
  398.    if (ret)
  399.       goto fail;
  400.    if (is_h264) {
  401.       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP,
  402.                            0,
  403.                            2 * (dec->vpring_deblock +
  404.                                 dec->vpring_residual +
  405.                                 dec->vpring_ctrl +
  406.                                 0x1000),
  407.                            NULL, &dec->vpring);
  408.       if (ret)
  409.          goto fail;
  410.       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP,
  411.                            0,
  412.                            (max_references + 1) * dec->frame_mbs * 0x40 +
  413.                            dec->frame_size + 0x2000,
  414.                            NULL, &dec->mbring);
  415.       if (ret)
  416.          goto fail;
  417.       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART,
  418.                            0, 2 * (0x700 + MAX2(0x40000, 0x800 + 0x180 * dec->frame_mbs)),
  419.                            NULL, &dec->bitstream);
  420.       if (ret)
  421.          goto fail;
  422.       ret = nouveau_bo_map(dec->bitstream, NOUVEAU_BO_WR, dec->client);
  423.       if (ret)
  424.          goto fail;
  425.       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART,
  426.                            0, 0x2000, NULL, &dec->vp_params);
  427.       if (ret)
  428.          goto fail;
  429.       ret = nouveau_bo_map(dec->vp_params, NOUVEAU_BO_WR, dec->client);
  430.       if (ret)
  431.          goto fail;
  432.    }
  433.    if (is_mpeg12) {
  434.       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART,
  435.                            0,
  436.                            align(0x20 * mb(width) * mb(height), 0x100) +
  437.                            (6 * 64 * 8) * mb(width) * mb(height) + 0x100,
  438.                            NULL, &dec->mpeg12_bo);
  439.       if (ret)
  440.          goto fail;
  441.       ret = nouveau_bo_map(dec->mpeg12_bo, NOUVEAU_BO_WR, dec->client);
  442.       if (ret)
  443.          goto fail;
  444.    }
  445.  
  446.    ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
  447.                         0, 0x1000, NULL, &dec->fence);
  448.    if (ret)
  449.       goto fail;
  450.    ret = nouveau_bo_map(dec->fence, NOUVEAU_BO_WR, dec->client);
  451.    if (ret)
  452.       goto fail;
  453.    *(uint32_t *)dec->fence->map = 0;
  454.  
  455.    if (is_h264) {
  456.       nouveau_pushbuf_bufctx(bsp_push, dec->bsp_bufctx);
  457.       nouveau_bufctx_refn(dec->bsp_bufctx, 0,
  458.                           dec->bsp_fw, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
  459.       nouveau_bufctx_refn(dec->bsp_bufctx, 0,
  460.                           dec->bsp_data, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
  461.    }
  462.  
  463.    nouveau_pushbuf_bufctx(vp_push, dec->vp_bufctx);
  464.    nouveau_bufctx_refn(dec->vp_bufctx, 0, dec->vp_fw,
  465.                        NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
  466.    nouveau_bufctx_refn(dec->vp_bufctx, 0, dec->vp_data,
  467.                        NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
  468.  
  469.    if (is_h264 && !ret)
  470.       ret = nouveau_object_new(dec->bsp_channel, 0xbeef74b0, 0x74b0,
  471.                                NULL, 0, &dec->bsp);
  472.  
  473.    if (!ret)
  474.       ret = nouveau_object_new(dec->vp_channel, 0xbeef7476, 0x7476,
  475.                                NULL, 0, &dec->vp);
  476.  
  477.    if (ret)
  478.       goto fail;
  479.  
  480.  
  481.    if (is_h264) {
  482.       /* Zero out some parts of mbring/vpring. there's gotta be some cleaner way
  483.        * of doing this... perhaps makes sense to just copy the relevant logic
  484.        * here. */
  485.       color.f[0] = color.f[1] = color.f[2] = color.f[3] = 0;
  486.       surf.offset = dec->frame_size;
  487.       surf.width = 64;
  488.       surf.height = (max_references + 1) * dec->frame_mbs / 4;
  489.       surf.depth = 1;
  490.       surf.base.format = PIPE_FORMAT_B8G8R8A8_UNORM;
  491.       surf.base.u.tex.level = 0;
  492.       surf.base.texture = &mip.base.base;
  493.       mip.level[0].tile_mode = 0;
  494.       mip.level[0].pitch = surf.width * 4;
  495.       mip.base.domain = NOUVEAU_BO_VRAM;
  496.       mip.base.bo = dec->mbring;
  497.       context->clear_render_target(context, &surf.base, &color, 0, 0, 64, 4760);
  498.       surf.offset = dec->vpring->size / 2 - 0x1000;
  499.       surf.width = 1024;
  500.       surf.height = 1;
  501.       mip.level[0].pitch = surf.width * 4;
  502.       mip.base.bo = dec->vpring;
  503.       context->clear_render_target(context, &surf.base, &color, 0, 0, 1024, 1);
  504.       surf.offset = dec->vpring->size - 0x1000;
  505.       context->clear_render_target(context, &surf.base, &color, 0, 0, 1024, 1);
  506.  
  507.       PUSH_SPACE(screen->pushbuf, 5);
  508.       PUSH_REFN(screen->pushbuf, dec->fence, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
  509.       /* The clear_render_target is done via 3D engine, so use it to write to a
  510.        * sempahore to indicate that it's done.
  511.        */
  512.       BEGIN_NV04(screen->pushbuf, NV50_3D(QUERY_ADDRESS_HIGH), 4);
  513.       PUSH_DATAh(screen->pushbuf, dec->fence->offset);
  514.       PUSH_DATA (screen->pushbuf, dec->fence->offset);
  515.       PUSH_DATA (screen->pushbuf, 1);
  516.       PUSH_DATA (screen->pushbuf, 0xf010);
  517.       PUSH_KICK (screen->pushbuf);
  518.  
  519.       PUSH_SPACE(bsp_push, 2 + 12 + 2 + 4 + 3);
  520.  
  521.       BEGIN_NV04(bsp_push, SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
  522.       PUSH_DATA (bsp_push, dec->bsp->handle);
  523.  
  524.       BEGIN_NV04(bsp_push, SUBC_BSP(0x180), 11);
  525.       for (i = 0; i < 11; i++)
  526.          PUSH_DATA(bsp_push, nv04_data.vram);
  527.       BEGIN_NV04(bsp_push, SUBC_BSP(0x1b8), 1);
  528.       PUSH_DATA (bsp_push, nv04_data.vram);
  529.  
  530.       BEGIN_NV04(bsp_push, SUBC_BSP(0x600), 3);
  531.       PUSH_DATAh(bsp_push, dec->bsp_fw->offset);
  532.       PUSH_DATA (bsp_push, dec->bsp_fw->offset);
  533.       PUSH_DATA (bsp_push, dec->bsp_fw->size);
  534.  
  535.       BEGIN_NV04(bsp_push, SUBC_BSP(0x628), 2);
  536.       PUSH_DATA (bsp_push, dec->bsp_data->offset >> 8);
  537.       PUSH_DATA (bsp_push, dec->bsp_data->size);
  538.       PUSH_KICK (bsp_push);
  539.    }
  540.  
  541.    PUSH_SPACE(vp_push, 2 + 12 + 2 + 4 + 3);
  542.  
  543.    BEGIN_NV04(vp_push, SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
  544.    PUSH_DATA (vp_push, dec->vp->handle);
  545.  
  546.    BEGIN_NV04(vp_push, SUBC_VP(0x180), 11);
  547.    for (i = 0; i < 11; i++)
  548.       PUSH_DATA(vp_push, nv04_data.vram);
  549.  
  550.    BEGIN_NV04(vp_push, SUBC_VP(0x1b8), 1);
  551.    PUSH_DATA (vp_push, nv04_data.vram);
  552.  
  553.    BEGIN_NV04(vp_push, SUBC_VP(0x600), 3);
  554.    PUSH_DATAh(vp_push, dec->vp_fw->offset);
  555.    PUSH_DATA (vp_push, dec->vp_fw->offset);
  556.    PUSH_DATA (vp_push, dec->vp_fw->size);
  557.  
  558.    BEGIN_NV04(vp_push, SUBC_VP(0x628), 2);
  559.    PUSH_DATA (vp_push, dec->vp_data->offset >> 8);
  560.    PUSH_DATA (vp_push, dec->vp_data->size);
  561.    PUSH_KICK (vp_push);
  562.  
  563.    return &dec->base;
  564. fail:
  565.    nv84_decoder_destroy(&dec->base);
  566.    return NULL;
  567. }
  568.  
  569. static struct pipe_sampler_view **
  570. nv84_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
  571. {
  572.    struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer;
  573.    return buf->sampler_view_planes;
  574. }
  575.  
  576. static struct pipe_sampler_view **
  577. nv84_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
  578. {
  579.    struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer;
  580.    return buf->sampler_view_components;
  581. }
  582.  
  583. static struct pipe_surface **
  584. nv84_video_buffer_surfaces(struct pipe_video_buffer *buffer)
  585. {
  586.    struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer;
  587.    return buf->surfaces;
  588. }
  589.  
  590. static void
  591. nv84_video_buffer_destroy(struct pipe_video_buffer *buffer)
  592. {
  593.    struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer;
  594.    unsigned i;
  595.  
  596.    assert(buf);
  597.  
  598.    for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
  599.       pipe_resource_reference(&buf->resources[i], NULL);
  600.       pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
  601.       pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
  602.       pipe_surface_reference(&buf->surfaces[i * 2], NULL);
  603.       pipe_surface_reference(&buf->surfaces[i * 2 + 1], NULL);
  604.    }
  605.  
  606.    nouveau_bo_ref(NULL, &buf->interlaced);
  607.    nouveau_bo_ref(NULL, &buf->full);
  608.  
  609.    FREE(buffer);
  610. }
  611.  
  612. struct pipe_video_buffer *
  613. nv84_video_buffer_create(struct pipe_context *pipe,
  614.                          const struct pipe_video_buffer *template)
  615. {
  616.    struct nv84_video_buffer *buffer;
  617.    struct pipe_resource templ;
  618.    unsigned i, j, component;
  619.    struct pipe_sampler_view sv_templ;
  620.    struct pipe_surface surf_templ;
  621.    struct nv50_miptree *mt0, *mt1;
  622.    struct nouveau_bo *empty = NULL;
  623.    struct nouveau_screen *screen = &((struct nv50_context *)pipe)->screen->base;
  624.    union nouveau_bo_config cfg;
  625.    unsigned bo_size;
  626.  
  627.    if (getenv("XVMC_VL") || template->buffer_format != PIPE_FORMAT_NV12)
  628.       return vl_video_buffer_create(pipe, template);
  629.  
  630.    if (!template->interlaced) {
  631.       debug_printf("Require interlaced video buffers\n");
  632.       return NULL;
  633.    }
  634.    if (template->chroma_format != PIPE_VIDEO_CHROMA_FORMAT_420) {
  635.       debug_printf("Must use 4:2:0 format\n");
  636.       return NULL;
  637.    }
  638.  
  639.    /*
  640.     * Note that there are always going to be exactly two planes, one for Y,
  641.     * and one for UV. These are also the resources. VP expects these to be
  642.     * adjacent, so they need to belong to the same BO.
  643.     */
  644.  
  645.    buffer = CALLOC_STRUCT(nv84_video_buffer);
  646.    if (!buffer) return NULL;
  647.  
  648.    buffer->mvidx = -1;
  649.  
  650.    buffer->base.buffer_format = template->buffer_format;
  651.    buffer->base.context = pipe;
  652.    buffer->base.destroy = nv84_video_buffer_destroy;
  653.    buffer->base.chroma_format = template->chroma_format;
  654.    buffer->base.width = template->width;
  655.    buffer->base.height = template->height;
  656.    buffer->base.get_sampler_view_planes = nv84_video_buffer_sampler_view_planes;
  657.    buffer->base.get_sampler_view_components = nv84_video_buffer_sampler_view_components;
  658.    buffer->base.get_surfaces = nv84_video_buffer_surfaces;
  659.    buffer->base.interlaced = true;
  660.  
  661.    memset(&templ, 0, sizeof(templ));
  662.    templ.target = PIPE_TEXTURE_2D_ARRAY;
  663.    templ.depth0 = 1;
  664.    templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
  665.    templ.format = PIPE_FORMAT_R8_UNORM;
  666.    templ.width0 = align(template->width, 2);
  667.    templ.height0 = align(template->height, 4) / 2;
  668.    templ.flags = NV50_RESOURCE_FLAG_VIDEO;
  669.    templ.array_size = 2;
  670.  
  671.    cfg.nv50.tile_mode = 0x20;
  672.    cfg.nv50.memtype = 0x70;
  673.  
  674.    buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ);
  675.    if (!buffer->resources[0])
  676.       goto error;
  677.  
  678.    templ.format = PIPE_FORMAT_R8G8_UNORM;
  679.    templ.width0 /= 2;
  680.    templ.height0 /= 2;
  681.    buffer->resources[1] = pipe->screen->resource_create(pipe->screen, &templ);
  682.    if (!buffer->resources[1])
  683.       goto error;
  684.  
  685.    mt0 = nv50_miptree(buffer->resources[0]);
  686.    mt1 = nv50_miptree(buffer->resources[1]);
  687.  
  688.    bo_size = mt0->total_size + mt1->total_size;
  689.    if (nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP, 0,
  690.                       bo_size, &cfg, &buffer->interlaced))
  691.       goto error;
  692.    /* XXX Change reference frame management so that this is only allocated in
  693.     * the decoder when necessary. */
  694.    if (nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP, 0,
  695.                       bo_size, &cfg, &buffer->full))
  696.       goto error;
  697.  
  698.    mt0->base.bo = buffer->interlaced;
  699.    mt0->base.domain = NOUVEAU_BO_VRAM;
  700.    mt0->base.offset = 0;
  701.    mt0->base.address = buffer->interlaced->offset + mt0->base.offset;
  702.    nouveau_bo_ref(buffer->interlaced, &empty);
  703.  
  704.    mt1->base.bo = buffer->interlaced;
  705.    mt1->base.domain = NOUVEAU_BO_VRAM;
  706.    mt1->base.offset = mt0->layer_stride * 2;
  707.    mt1->base.address = buffer->interlaced->offset + mt1->base.offset;
  708.    nouveau_bo_ref(buffer->interlaced, &empty);
  709.  
  710.    memset(&sv_templ, 0, sizeof(sv_templ));
  711.    for (component = 0, i = 0; i < 2; ++i ) {
  712.       struct pipe_resource *res = buffer->resources[i];
  713.       unsigned nr_components = util_format_get_nr_components(res->format);
  714.  
  715.       u_sampler_view_default_template(&sv_templ, res, res->format);
  716.       buffer->sampler_view_planes[i] =
  717.          pipe->create_sampler_view(pipe, res, &sv_templ);
  718.       if (!buffer->sampler_view_planes[i])
  719.          goto error;
  720.  
  721.       for (j = 0; j < nr_components; ++j, ++component) {
  722.          sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b =
  723.             PIPE_SWIZZLE_RED + j;
  724.          sv_templ.swizzle_a = PIPE_SWIZZLE_ONE;
  725.  
  726.          buffer->sampler_view_components[component] =
  727.             pipe->create_sampler_view(pipe, res, &sv_templ);
  728.          if (!buffer->sampler_view_components[component])
  729.             goto error;
  730.       }
  731.    }
  732.  
  733.    memset(&surf_templ, 0, sizeof(surf_templ));
  734.    for (j = 0; j < 2; ++j) {
  735.       surf_templ.format = buffer->resources[j]->format;
  736.       surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 0;
  737.       buffer->surfaces[j * 2] =
  738.          pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
  739.       if (!buffer->surfaces[j * 2])
  740.          goto error;
  741.  
  742.       surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 1;
  743.       buffer->surfaces[j * 2 + 1] =
  744.          pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
  745.       if (!buffer->surfaces[j * 2 + 1])
  746.          goto error;
  747.    }
  748.  
  749.    return &buffer->base;
  750.  
  751. error:
  752.    nv84_video_buffer_destroy(&buffer->base);
  753.    return NULL;
  754. }
  755.  
  756. int
  757. nv84_screen_get_video_param(struct pipe_screen *pscreen,
  758.                             enum pipe_video_profile profile,
  759.                             enum pipe_video_cap param)
  760. {
  761.    switch (param) {
  762.    case PIPE_VIDEO_CAP_SUPPORTED:
  763.       return u_reduce_video_profile(profile) == PIPE_VIDEO_CODEC_MPEG4_AVC ||
  764.          u_reduce_video_profile(profile) == PIPE_VIDEO_CODEC_MPEG12;
  765.    case PIPE_VIDEO_CAP_NPOT_TEXTURES:
  766.       return 1;
  767.    case PIPE_VIDEO_CAP_MAX_WIDTH:
  768.    case PIPE_VIDEO_CAP_MAX_HEIGHT:
  769.       return 2048;
  770.    case PIPE_VIDEO_CAP_PREFERED_FORMAT:
  771.       return PIPE_FORMAT_NV12;
  772.    case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
  773.    case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
  774.       return true;
  775.    case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
  776.       return false;
  777.    default:
  778.       debug_printf("unknown video param: %d\n", param);
  779.       return 0;
  780.    }
  781. }
  782.  
  783. boolean
  784. nv84_screen_video_supported(struct pipe_screen *screen,
  785.                             enum pipe_format format,
  786.                             enum pipe_video_profile profile)
  787. {
  788.    if (profile != PIPE_VIDEO_PROFILE_UNKNOWN)
  789.       return format == PIPE_FORMAT_NV12;
  790.  
  791.    return vl_video_buffer_is_format_supported(screen, format, profile);
  792. }
  793.