1/*
2 * Copyright 2011-2013 Maarten Lankhorst
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23#include "nvc0/nvc0_video.h"
24
25#include "util/u_sampler.h"
26#include "util/format/u_format.h"
27
28static void
29nvc0_decoder_begin_frame(struct pipe_video_codec *decoder,
30                         struct pipe_video_buffer *target,
31                         struct pipe_picture_desc *picture)
32{
33   struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
34   uint32_t comm_seq = ++dec->fence_seq;
35   ASSERTED unsigned ret = 0; /* used in debug checks */
36
37   assert(dec);
38   assert(target);
39   assert(target->buffer_format == PIPE_FORMAT_NV12);
40
41   ret = nvc0_decoder_bsp_begin(dec, comm_seq);
42
43   assert(ret == 2);
44}
45
46static void
47nvc0_decoder_decode_bitstream(struct pipe_video_codec *decoder,
48                              struct pipe_video_buffer *video_target,
49                              struct pipe_picture_desc *picture,
50                              unsigned num_buffers,
51                              const void *const *data,
52                              const unsigned *num_bytes)
53{
54   struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
55   uint32_t comm_seq = dec->fence_seq;
56   ASSERTED unsigned ret = 0; /* used in debug checks */
57
58   assert(decoder);
59
60   ret = nvc0_decoder_bsp_next(dec, comm_seq, num_buffers, data, num_bytes);
61
62   assert(ret == 2);
63}
64
65static void
66nvc0_decoder_end_frame(struct pipe_video_codec *decoder,
67                       struct pipe_video_buffer *video_target,
68                       struct pipe_picture_desc *picture)
69{
70   struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
71   struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target;
72   uint32_t comm_seq = dec->fence_seq;
73   union pipe_desc desc;
74
75   unsigned vp_caps, is_ref;
76   ASSERTED unsigned ret; /* used in debug checks */
77   struct nouveau_vp3_video_buffer *refs[16] = {};
78
79   desc.base = picture;
80
81   ret = nvc0_decoder_bsp_end(dec, desc, target, comm_seq, &vp_caps, &is_ref, refs);
82
83   /* did we decode bitstream correctly? */
84   assert(ret == 2);
85
86   nvc0_decoder_vp(dec, desc, target, comm_seq, vp_caps, is_ref, refs);
87   nvc0_decoder_ppp(dec, desc, target, comm_seq);
88}
89
90struct pipe_video_codec *
91nvc0_create_decoder(struct pipe_context *context,
92                    const struct pipe_video_codec *templ)
93{
94   struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base;
95   struct nouveau_vp3_decoder *dec;
96   struct nouveau_pushbuf **push;
97   union nouveau_bo_config cfg;
98   bool kepler = screen->device->chipset >= 0xe0;
99
100   cfg.nvc0.tile_mode = 0x10;
101   cfg.nvc0.memtype = 0xfe;
102
103   int ret, i;
104   uint32_t codec = 1, ppp_codec = 3;
105   uint32_t timeout;
106   u32 tmp_size = 0;
107
108   if (getenv("XVMC_VL"))
109       return vl_create_decoder(context, templ);
110
111   if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
112      debug_printf("%x\n", templ->entrypoint);
113      return NULL;
114   }
115
116   dec = CALLOC_STRUCT(nouveau_vp3_decoder);
117   if (!dec)
118      return NULL;
119   dec->client = screen->client;
120   dec->base = *templ;
121   nouveau_vp3_decoder_init_common(&dec->base);
122
123   if (!kepler) {
124      dec->bsp_idx = 5;
125      dec->vp_idx = 6;
126      dec->ppp_idx = 7;
127   } else {
128      dec->bsp_idx = 2;
129      dec->vp_idx = 2;
130      dec->ppp_idx = 2;
131   }
132
133   for (i = 0; i < 3; ++i)
134      if (i && !kepler) {
135         dec->channel[i] = dec->channel[0];
136         dec->pushbuf[i] = dec->pushbuf[0];
137      } else {
138         void *data;
139         u32 size;
140         struct nvc0_fifo nvc0_args = {};
141         struct nve0_fifo nve0_args = {};
142
143         if (!kepler) {
144            size = sizeof(nvc0_args);
145            data = &nvc0_args;
146         } else {
147            unsigned engine[] = {
148               NVE0_FIFO_ENGINE_BSP,
149               NVE0_FIFO_ENGINE_VP,
150               NVE0_FIFO_ENGINE_PPP
151            };
152
153            nve0_args.engine = engine[i];
154            size = sizeof(nve0_args);
155            data = &nve0_args;
156         }
157
158         ret = nouveau_object_new(&screen->device->object, 0,
159                                  NOUVEAU_FIFO_CHANNEL_CLASS,
160                                  data, size, &dec->channel[i]);
161
162         if (!ret)
163            ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4,
164                                   32 * 1024, true, &dec->pushbuf[i]);
165         if (ret)
166            break;
167      }
168   push = dec->pushbuf;
169
170   if (!kepler) {
171      if (!ret)
172         ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp);
173      if (!ret)
174         ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp);
175      if (!ret)
176         ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp);
177   } else {
178      if (!ret)
179         ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp);
180      if (!ret)
181         ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp);
182      if (!ret)
183         ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp);
184   }
185   if (ret)
186      goto fail;
187
188   BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
189   PUSH_DATA (push[0], dec->bsp->handle);
190
191   BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
192   PUSH_DATA (push[1], dec->vp->handle);
193
194   BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
195   PUSH_DATA (push[2], dec->ppp->handle);
196
197   dec->base.context = context;
198   dec->base.begin_frame = nvc0_decoder_begin_frame;
199   dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
200   dec->base.end_frame = nvc0_decoder_end_frame;
201
202   for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
203      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
204                           0, 1 << 20, &cfg, &dec->bsp_bo[i]);
205   if (!ret) {
206      /* total fudge factor... just has to be bigger for higher bitrates? */
207      unsigned inter_size = align(templ->width * templ->height * 2, 4 << 20);
208      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
209                           0x100, inter_size, &cfg, &dec->inter_bo[0]);
210   }
211   if (!ret) {
212      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
213                           0x100, dec->inter_bo[0]->size, &cfg,
214                           &dec->inter_bo[1]);
215   }
216   if (ret)
217      goto fail;
218   switch (u_reduce_video_profile(templ->profile)) {
219   case PIPE_VIDEO_FORMAT_MPEG12: {
220      codec = 1;
221      assert(templ->max_references <= 2);
222      break;
223   }
224   case PIPE_VIDEO_FORMAT_MPEG4: {
225      codec = 4;
226      tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
227      assert(templ->max_references <= 2);
228      break;
229   }
230   case PIPE_VIDEO_FORMAT_VC1: {
231      ppp_codec = codec = 2;
232      tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
233      assert(templ->max_references <= 2);
234      break;
235   }
236   case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
237      codec = 3;
238      dec->tmp_stride = 16 * mb_half(templ->width) * nouveau_vp3_video_align(templ->height) * 3 / 2;
239      tmp_size = dec->tmp_stride * (templ->max_references + 1);
240      assert(templ->max_references <= 16);
241      break;
242   }
243   default:
244      fprintf(stderr, "invalid codec\n");
245      goto fail;
246   }
247
248   if (screen->device->chipset < 0xd0) {
249      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
250                           0x4000, &cfg, &dec->fw_bo);
251      if (ret)
252         goto fail;
253
254      ret = nouveau_vp3_load_firmware(dec, templ->profile, screen->device->chipset);
255      if (ret)
256         goto fw_fail;
257   }
258
259   if (codec != 3) {
260      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
261                           0x400, &cfg, &dec->bitplane_bo);
262      if (ret)
263         goto fail;
264   }
265
266   dec->ref_stride = mb(templ->width)*16 * (mb_half(templ->height)*32 + nouveau_vp3_video_align(templ->height)/2);
267   ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
268                        dec->ref_stride * (templ->max_references+2) + tmp_size,
269                        &cfg, &dec->ref_bo);
270   if (ret)
271      goto fail;
272
273   timeout = 0;
274
275   BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2);
276   PUSH_DATA (push[0], codec);
277   PUSH_DATA (push[0], timeout);
278
279   BEGIN_NVC0(push[1], SUBC_VP(0x200), 2);
280   PUSH_DATA (push[1], codec);
281   PUSH_DATA (push[1], timeout);
282
283   BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2);
284   PUSH_DATA (push[2], ppp_codec);
285   PUSH_DATA (push[2], timeout);
286
287   ++dec->fence_seq;
288
289#if NOUVEAU_VP3_DEBUG_FENCE
290   ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
291                        0, 0x1000, NULL, &dec->fence_bo);
292   if (ret)
293      goto fail;
294
295   nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
296   dec->fence_map = dec->fence_bo->map;
297   dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
298   dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
299
300   /* So lets test if the fence is working? */
301   nouveau_pushbuf_space(push[0], 16, 1, 0);
302   PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
303   BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
304   PUSH_DATAh(push[0], dec->fence_bo->offset);
305   PUSH_DATA (push[0], dec->fence_bo->offset);
306   PUSH_DATA (push[0], dec->fence_seq);
307
308   BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
309   PUSH_DATA (push[0], 0);
310   PUSH_KICK (push[0]);
311
312   nouveau_pushbuf_space(push[1], 16, 1, 0);
313   PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
314   BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
315   PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
316   PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
317   PUSH_DATA (push[1], dec->fence_seq);
318
319   BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
320   PUSH_DATA (push[1], 0);
321   PUSH_KICK (push[1]);
322
323   nouveau_pushbuf_space(push[2], 16, 1, 0);
324   PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
325   BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
326   PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
327   PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
328   PUSH_DATA (push[2], dec->fence_seq);
329
330   BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
331   PUSH_DATA (push[2], 0);
332   PUSH_KICK (push[2]);
333
334   usleep(100);
335   while (dec->fence_seq > dec->fence_map[0] ||
336          dec->fence_seq > dec->fence_map[4] ||
337          dec->fence_seq > dec->fence_map[8]) {
338      debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
339      usleep(100);
340   }
341   debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
342#endif
343
344   return &dec->base;
345
346fw_fail:
347   debug_printf("Cannot create decoder without firmware..\n");
348   dec->base.destroy(&dec->base);
349   return NULL;
350
351fail:
352   debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
353   dec->base.destroy(&dec->base);
354   return NULL;
355}
356
357struct pipe_video_buffer *
358nvc0_video_buffer_create(struct pipe_context *pipe,
359                         const struct pipe_video_buffer *templat)
360{
361   return nouveau_vp3_video_buffer_create(
362         pipe, templat, NVC0_RESOURCE_FLAG_VIDEO);
363}
364