nvc0: refactor video buffer management logic into nouveau_vp3
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_video.c
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_video.h"
24
25 #include "util/u_sampler.h"
26 #include "util/u_format.h"
27
28 #include <sys/mman.h>
29 #include <fcntl.h>
30
31 int
32 nvc0_screen_get_video_param(struct pipe_screen *pscreen,
33 enum pipe_video_profile profile,
34 enum pipe_video_cap param)
35 {
36 switch (param) {
37 case PIPE_VIDEO_CAP_SUPPORTED:
38 return profile >= PIPE_VIDEO_PROFILE_MPEG1;
39 case PIPE_VIDEO_CAP_NPOT_TEXTURES:
40 return 1;
41 case PIPE_VIDEO_CAP_MAX_WIDTH:
42 case PIPE_VIDEO_CAP_MAX_HEIGHT:
43 return nouveau_screen(pscreen)->device->chipset < 0xd0 ? 2048 : 4096;
44 case PIPE_VIDEO_CAP_PREFERED_FORMAT:
45 return PIPE_FORMAT_NV12;
46 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
47 case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
48 return true;
49 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
50 return false;
51 case PIPE_VIDEO_CAP_MAX_LEVEL:
52 switch (profile) {
53 case PIPE_VIDEO_PROFILE_MPEG1:
54 return 0;
55 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
56 case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
57 return 3;
58 case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE:
59 return 3;
60 case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE:
61 return 5;
62 case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
63 return 1;
64 case PIPE_VIDEO_PROFILE_VC1_MAIN:
65 return 2;
66 case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
67 return 4;
68 case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
69 case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
70 case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
71 return 41;
72 default:
73 debug_printf("unknown video profile: %d\n", profile);
74 return 0;
75 }
76 default:
77 debug_printf("unknown video param: %d\n", param);
78 return 0;
79 }
80 }
81
82 static void
83 nvc0_decoder_decode_bitstream(struct pipe_video_decoder *decoder,
84 struct pipe_video_buffer *video_target,
85 struct pipe_picture_desc *picture,
86 unsigned num_buffers,
87 const void *const *data,
88 const unsigned *num_bytes)
89 {
90 struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
91 struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target;
92 uint32_t comm_seq = ++dec->fence_seq;
93 union pipe_desc desc;
94
95 unsigned vp_caps, is_ref, ret;
96 struct nouveau_vp3_video_buffer *refs[16] = {};
97
98 desc.base = picture;
99
100 assert(target->base.buffer_format == PIPE_FORMAT_NV12);
101
102 ret = nvc0_decoder_bsp(dec, desc, target, comm_seq,
103 num_buffers, data, num_bytes,
104 &vp_caps, &is_ref, refs);
105
106 /* did we decode bitstream correctly? */
107 assert(ret == 2);
108
109 nvc0_decoder_vp(dec, desc, target, comm_seq, vp_caps, is_ref, refs);
110 nvc0_decoder_ppp(dec, desc, target, comm_seq);
111 }
112
113 static void
114 nvc0_decoder_flush(struct pipe_video_decoder *decoder)
115 {
116 struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
117 (void)dec;
118 }
119
120 static void
121 nvc0_decoder_begin_frame(struct pipe_video_decoder *decoder,
122 struct pipe_video_buffer *target,
123 struct pipe_picture_desc *picture)
124 {
125 }
126
127 static void
128 nvc0_decoder_end_frame(struct pipe_video_decoder *decoder,
129 struct pipe_video_buffer *target,
130 struct pipe_picture_desc *picture)
131 {
132 }
133
134 static void
135 nvc0_decoder_destroy(struct pipe_video_decoder *decoder)
136 {
137 struct nvc0_decoder *dec = (struct nvc0_decoder *)decoder;
138 int i;
139
140 nouveau_bo_ref(NULL, &dec->ref_bo);
141 nouveau_bo_ref(NULL, &dec->bitplane_bo);
142 nouveau_bo_ref(NULL, &dec->inter_bo[0]);
143 nouveau_bo_ref(NULL, &dec->inter_bo[1]);
144 #ifdef NVC0_DEBUG_FENCE
145 nouveau_bo_ref(NULL, &dec->fence_bo);
146 #endif
147 nouveau_bo_ref(NULL, &dec->fw_bo);
148
149 for (i = 0; i < NVC0_VIDEO_QDEPTH; ++i)
150 nouveau_bo_ref(NULL, &dec->bsp_bo[i]);
151
152 nouveau_object_del(&dec->bsp);
153 nouveau_object_del(&dec->vp);
154 nouveau_object_del(&dec->ppp);
155
156 if (dec->channel[0] != dec->channel[1]) {
157 for (i = 0; i < 3; ++i) {
158 nouveau_pushbuf_del(&dec->pushbuf[i]);
159 nouveau_object_del(&dec->channel[i]);
160 }
161 } else {
162 nouveau_pushbuf_del(dec->pushbuf);
163 nouveau_object_del(dec->channel);
164 }
165
166 FREE(dec);
167 }
168
169 static void nvc0_video_getpath(enum pipe_video_profile profile, char *path)
170 {
171 switch (u_reduce_video_profile(profile)) {
172 case PIPE_VIDEO_CODEC_MPEG12: {
173 sprintf(path, "/lib/firmware/nouveau/vuc-mpeg12-0");
174 break;
175 }
176 case PIPE_VIDEO_CODEC_MPEG4: {
177 sprintf(path, "/lib/firmware/nouveau/vuc-mpeg4-0");
178 break;
179 }
180 case PIPE_VIDEO_CODEC_VC1: {
181 sprintf(path, "/lib/firmware/nouveau/vuc-vc1-0");
182 break;
183 }
184 case PIPE_VIDEO_CODEC_MPEG4_AVC: {
185 sprintf(path, "/lib/firmware/nouveau/vuc-h264-0");
186 break;
187 }
188 default: assert(0);
189 }
190 }
191
192 struct pipe_video_decoder *
193 nvc0_create_decoder(struct pipe_context *context,
194 enum pipe_video_profile profile,
195 enum pipe_video_entrypoint entrypoint,
196 enum pipe_video_chroma_format chroma_format,
197 unsigned width, unsigned height, unsigned max_references,
198 bool chunked_decode)
199 {
200 struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base;
201 struct nvc0_decoder *dec;
202 struct nouveau_pushbuf **push;
203 union nouveau_bo_config cfg;
204 bool kepler = screen->device->chipset >= 0xe0;
205
206 cfg.nvc0.tile_mode = 0x10;
207 cfg.nvc0.memtype = 0xfe;
208
209 int ret, i;
210 uint32_t codec = 1, ppp_codec = 3;
211 uint32_t timeout;
212 u32 tmp_size = 0;
213
214 if (getenv("XVMC_VL"))
215 return vl_create_decoder(context, profile, entrypoint,
216 chroma_format, width, height,
217 max_references, chunked_decode);
218
219 if (entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
220 debug_printf("%x\n", entrypoint);
221 return NULL;
222 }
223
224 dec = CALLOC_STRUCT(nvc0_decoder);
225 if (!dec)
226 return NULL;
227 dec->client = screen->client;
228
229 if (!kepler) {
230 dec->bsp_idx = 5;
231 dec->vp_idx = 6;
232 dec->ppp_idx = 7;
233 } else {
234 dec->bsp_idx = 2;
235 dec->vp_idx = 2;
236 dec->ppp_idx = 2;
237 }
238
239 for (i = 0; i < 3; ++i)
240 if (i && !kepler) {
241 dec->channel[i] = dec->channel[0];
242 dec->pushbuf[i] = dec->pushbuf[0];
243 } else {
244 void *data;
245 u32 size;
246 struct nvc0_fifo nvc0_args = {};
247 struct nve0_fifo nve0_args = {};
248
249 if (!kepler) {
250 size = sizeof(nvc0_args);
251 data = &nvc0_args;
252 } else {
253 unsigned engine[] = {
254 NVE0_FIFO_ENGINE_BSP,
255 NVE0_FIFO_ENGINE_VP,
256 NVE0_FIFO_ENGINE_PPP
257 };
258
259 nve0_args.engine = engine[i];
260 size = sizeof(nve0_args);
261 data = &nve0_args;
262 }
263
264 ret = nouveau_object_new(&screen->device->object, 0,
265 NOUVEAU_FIFO_CHANNEL_CLASS,
266 data, size, &dec->channel[i]);
267
268 if (!ret)
269 ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4,
270 32 * 1024, true, &dec->pushbuf[i]);
271 if (ret)
272 break;
273 }
274 push = dec->pushbuf;
275
276 if (!kepler) {
277 if (!ret)
278 ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp);
279 if (!ret)
280 ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp);
281 if (!ret)
282 ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp);
283 } else {
284 if (!ret)
285 ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp);
286 if (!ret)
287 ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp);
288 if (!ret)
289 ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp);
290 }
291 if (ret)
292 goto fail;
293
294 BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
295 PUSH_DATA (push[0], dec->bsp->handle);
296
297 BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
298 PUSH_DATA (push[1], dec->vp->handle);
299
300 BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
301 PUSH_DATA (push[2], dec->ppp->handle);
302
303 dec->base.context = context;
304 dec->base.profile = profile;
305 dec->base.entrypoint = entrypoint;
306 dec->base.chroma_format = chroma_format;
307 dec->base.width = width;
308 dec->base.height = height;
309 dec->base.max_references = max_references;
310 dec->base.destroy = nvc0_decoder_destroy;
311 dec->base.flush = nvc0_decoder_flush;
312 dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
313 dec->base.begin_frame = nvc0_decoder_begin_frame;
314 dec->base.end_frame = nvc0_decoder_end_frame;
315
316 for (i = 0; i < NVC0_VIDEO_QDEPTH && !ret; ++i)
317 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
318 0, 1 << 20, &cfg, &dec->bsp_bo[i]);
319 if (!ret)
320 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
321 0x100, 4 << 20, &cfg, &dec->inter_bo[0]);
322 if (!ret) {
323 if (!kepler)
324 nouveau_bo_ref(dec->inter_bo[0], &dec->inter_bo[1]);
325 else
326 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
327 0x100, dec->inter_bo[0]->size, &cfg,
328 &dec->inter_bo[1]);
329 }
330 if (ret)
331 goto fail;
332
333 switch (u_reduce_video_profile(profile)) {
334 case PIPE_VIDEO_CODEC_MPEG12: {
335 codec = 1;
336 assert(max_references <= 2);
337 break;
338 }
339 case PIPE_VIDEO_CODEC_MPEG4: {
340 codec = 4;
341 tmp_size = mb(height)*16 * mb(width)*16;
342 assert(max_references <= 2);
343 break;
344 }
345 case PIPE_VIDEO_CODEC_VC1: {
346 ppp_codec = codec = 2;
347 tmp_size = mb(height)*16 * mb(width)*16;
348 assert(max_references <= 2);
349 break;
350 }
351 case PIPE_VIDEO_CODEC_MPEG4_AVC: {
352 codec = 3;
353 dec->tmp_stride = 16 * mb_half(width) * nvc0_video_align(height) * 3 / 2;
354 tmp_size = dec->tmp_stride * (max_references + 1);
355 assert(max_references <= 16);
356 break;
357 }
358 default:
359 fprintf(stderr, "invalid codec\n");
360 goto fail;
361 }
362
363 if (screen->device->chipset < 0xd0) {
364 int fd;
365 char path[PATH_MAX];
366 ssize_t r;
367 uint32_t *end, endval;
368
369 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
370 0x4000, &cfg, &dec->fw_bo);
371 if (!ret)
372 ret = nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client);
373 if (ret)
374 goto fail;
375
376 nvc0_video_getpath(profile, path);
377
378 fd = open(path, O_RDONLY | O_CLOEXEC);
379 if (fd < 0) {
380 fprintf(stderr, "opening firmware file %s failed: %m\n", path);
381 goto fw_fail;
382 }
383 r = read(fd, dec->fw_bo->map, 0x4000);
384 close(fd);
385
386 if (r < 0) {
387 fprintf(stderr, "reading firmware file %s failed: %m\n", path);
388 goto fw_fail;
389 }
390
391 if (r == 0x4000) {
392 fprintf(stderr, "firmware file %s too large!\n", path);
393 goto fw_fail;
394 }
395
396 if (r & 0xff) {
397 fprintf(stderr, "firmware file %s wrong size!\n", path);
398 goto fw_fail;
399 }
400
401 end = dec->fw_bo->map + r - 4;
402 endval = *end;
403 while (endval == *end)
404 end--;
405
406 r = (intptr_t)end - (intptr_t)dec->fw_bo->map + 4;
407
408 switch (u_reduce_video_profile(profile)) {
409 case PIPE_VIDEO_CODEC_MPEG12: {
410 assert((r & 0xff) == 0xe0);
411 dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
412 break;
413 }
414 case PIPE_VIDEO_CODEC_MPEG4: {
415 assert((r & 0xff) == 0xe0);
416 dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
417 break;
418 }
419 case PIPE_VIDEO_CODEC_VC1: {
420 assert((r & 0xff) == 0xac);
421 dec->fw_sizes = (0x3ac<<16) | (r - 0x3ac);
422 break;
423 }
424 case PIPE_VIDEO_CODEC_MPEG4_AVC: {
425 assert((r & 0xff) == 0x70);
426 dec->fw_sizes = (0x370<<16) | (r - 0x370);
427 break;
428 }
429 default:
430 goto fw_fail;
431 }
432 munmap(dec->fw_bo->map, dec->fw_bo->size);
433 dec->fw_bo->map = NULL;
434 }
435
436 if (codec != 3) {
437 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
438 0x400, &cfg, &dec->bitplane_bo);
439 if (ret)
440 goto fail;
441 }
442
443 dec->ref_stride = mb(width)*16 * (mb_half(height)*32 + nvc0_video_align(height)/2);
444 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
445 dec->ref_stride * (max_references+2) + tmp_size,
446 &cfg, &dec->ref_bo);
447 if (ret)
448 goto fail;
449
450 timeout = 0;
451
452 BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2);
453 PUSH_DATA (push[0], codec);
454 PUSH_DATA (push[0], timeout);
455
456 BEGIN_NVC0(push[1], SUBC_VP(0x200), 2);
457 PUSH_DATA (push[1], codec);
458 PUSH_DATA (push[1], timeout);
459
460 BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2);
461 PUSH_DATA (push[2], ppp_codec);
462 PUSH_DATA (push[2], timeout);
463
464 ++dec->fence_seq;
465
466 #if NVC0_DEBUG_FENCE
467 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
468 0, 0x1000, NULL, &dec->fence_bo);
469 if (ret)
470 goto fail;
471
472 nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
473 dec->fence_map = dec->fence_bo->map;
474 dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
475 dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
476
477 /* So lets test if the fence is working? */
478 nouveau_pushbuf_space(push[0], 6, 1, 0);
479 PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
480 BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
481 PUSH_DATAh(push[0], dec->fence_bo->offset);
482 PUSH_DATA (push[0], dec->fence_bo->offset);
483 PUSH_DATA (push[0], dec->fence_seq);
484
485 BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
486 PUSH_DATA (push[0], 0);
487 PUSH_KICK (push[0]);
488
489 nouveau_pushbuf_space(push[1], 6, 1, 0);
490 PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
491 BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
492 PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
493 PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
494 PUSH_DATA (push[1], dec->fence_seq);
495
496 BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
497 PUSH_DATA (push[1], 0);
498 PUSH_KICK (push[1]);
499
500 nouveau_pushbuf_space(push[2], 6, 1, 0);
501 PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
502 BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
503 PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
504 PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
505 PUSH_DATA (push[2], dec->fence_seq);
506
507 BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
508 PUSH_DATA (push[2], 0);
509 PUSH_KICK (push[2]);
510
511 usleep(100);
512 while (dec->fence_seq > dec->fence_map[0] ||
513 dec->fence_seq > dec->fence_map[4] ||
514 dec->fence_seq > dec->fence_map[8]) {
515 debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
516 usleep(100);
517 }
518 debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
519 #endif
520
521 return &dec->base;
522
523 fw_fail:
524 debug_printf("Cannot create decoder without firmware..\n");
525 nvc0_decoder_destroy(&dec->base);
526 return NULL;
527
528 fail:
529 debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
530 nvc0_decoder_destroy(&dec->base);
531 return NULL;
532 }
533
534 struct pipe_video_buffer *
535 nvc0_video_buffer_create(struct pipe_context *pipe,
536 const struct pipe_video_buffer *templat)
537 {
538 return nouveau_vp3_video_buffer_create(
539 pipe, templat, NVC0_RESOURCE_FLAG_VIDEO);
540 }