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