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