2 * Copyright 2011-2013 Maarten Lankhorst
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include "nvc0_video.h"
25 #include "util/u_sampler.h"
26 #include "util/u_format.h"
32 nvc0_screen_get_video_param(struct pipe_screen
*pscreen
,
33 enum pipe_video_profile profile
,
34 enum pipe_video_cap param
)
37 case PIPE_VIDEO_CAP_SUPPORTED
:
38 return profile
>= PIPE_VIDEO_PROFILE_MPEG1
;
39 case PIPE_VIDEO_CAP_NPOT_TEXTURES
:
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
:
49 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE
:
52 debug_printf("unknown video param: %d\n", param
);
58 nvc0_decoder_decode_bitstream(struct pipe_video_decoder
*decoder
,
59 struct pipe_video_buffer
*video_target
,
60 struct pipe_picture_desc
*picture
,
62 const void *const *data
,
63 const unsigned *num_bytes
)
65 struct nvc0_decoder
*dec
= (struct nvc0_decoder
*)decoder
;
66 struct nvc0_video_buffer
*target
= (struct nvc0_video_buffer
*)video_target
;
67 uint32_t comm_seq
= ++dec
->fence_seq
;
70 unsigned vp_caps
, is_ref
, ret
;
71 struct nvc0_video_buffer
*refs
[16] = {};
75 assert(target
->base
.buffer_format
== PIPE_FORMAT_NV12
);
77 ret
= nvc0_decoder_bsp(dec
, desc
, target
, comm_seq
,
78 num_buffers
, data
, num_bytes
,
79 &vp_caps
, &is_ref
, refs
);
81 /* did we decode bitstream correctly? */
84 nvc0_decoder_vp(dec
, desc
, target
, comm_seq
, vp_caps
, is_ref
, refs
);
85 nvc0_decoder_ppp(dec
, desc
, target
, comm_seq
);
89 nvc0_decoder_flush(struct pipe_video_decoder
*decoder
)
91 struct nvc0_decoder
*dec
= (struct nvc0_decoder
*)decoder
;
96 nvc0_decoder_begin_frame(struct pipe_video_decoder
*decoder
,
97 struct pipe_video_buffer
*target
,
98 struct pipe_picture_desc
*picture
)
103 nvc0_decoder_end_frame(struct pipe_video_decoder
*decoder
,
104 struct pipe_video_buffer
*target
,
105 struct pipe_picture_desc
*picture
)
110 nvc0_decoder_destroy(struct pipe_video_decoder
*decoder
)
112 struct nvc0_decoder
*dec
= (struct nvc0_decoder
*)decoder
;
115 nouveau_bo_ref(NULL
, &dec
->ref_bo
);
116 nouveau_bo_ref(NULL
, &dec
->bitplane_bo
);
117 nouveau_bo_ref(NULL
, &dec
->inter_bo
[0]);
118 nouveau_bo_ref(NULL
, &dec
->inter_bo
[1]);
119 #ifdef NVC0_DEBUG_FENCE
120 nouveau_bo_ref(NULL
, &dec
->fence_bo
);
122 nouveau_bo_ref(NULL
, &dec
->fw_bo
);
124 for (i
= 0; i
< NVC0_VIDEO_QDEPTH
; ++i
)
125 nouveau_bo_ref(NULL
, &dec
->bsp_bo
[i
]);
127 nouveau_object_del(&dec
->bsp
);
128 nouveau_object_del(&dec
->vp
);
129 nouveau_object_del(&dec
->ppp
);
131 if (dec
->channel
[0] != dec
->channel
[1]) {
132 for (i
= 0; i
< 3; ++i
) {
133 nouveau_pushbuf_del(&dec
->pushbuf
[i
]);
134 nouveau_object_del(&dec
->channel
[i
]);
137 nouveau_pushbuf_del(dec
->pushbuf
);
138 nouveau_object_del(dec
->channel
);
144 static void nvc0_video_getpath(enum pipe_video_profile profile
, char *path
)
146 switch (u_reduce_video_profile(profile
)) {
147 case PIPE_VIDEO_CODEC_MPEG12
: {
148 sprintf(path
, "/lib/firmware/nouveau/vuc-mpeg12-0");
151 case PIPE_VIDEO_CODEC_MPEG4
: {
152 sprintf(path
, "/lib/firmware/nouveau/vuc-mpeg4-0");
155 case PIPE_VIDEO_CODEC_VC1
: {
156 sprintf(path
, "/lib/firmware/nouveau/vuc-vc1-%u", profile
- PIPE_VIDEO_PROFILE_VC1_SIMPLE
);
159 case PIPE_VIDEO_CODEC_MPEG4_AVC
: {
160 sprintf(path
, "/lib/firmware/nouveau/vuc-h264-0");
167 struct pipe_video_decoder
*
168 nvc0_create_decoder(struct pipe_context
*context
,
169 enum pipe_video_profile profile
,
170 enum pipe_video_entrypoint entrypoint
,
171 enum pipe_video_chroma_format chroma_format
,
172 unsigned width
, unsigned height
, unsigned max_references
,
175 struct nouveau_screen
*screen
= &((struct nvc0_context
*)context
)->screen
->base
;
176 struct nvc0_decoder
*dec
;
177 struct nouveau_pushbuf
**push
;
178 union nouveau_bo_config cfg
;
179 bool kepler
= screen
->device
->chipset
>= 0xe0;
181 cfg
.nvc0
.tile_mode
= 0x10;
182 cfg
.nvc0
.memtype
= 0xfe;
185 uint32_t codec
= 1, ppp_codec
= 3;
189 if (getenv("XVMC_VL"))
190 return vl_create_decoder(context
, profile
, entrypoint
,
191 chroma_format
, width
, height
,
192 max_references
, chunked_decode
);
194 if (entrypoint
!= PIPE_VIDEO_ENTRYPOINT_BITSTREAM
) {
195 debug_printf("%x\n", entrypoint
);
199 dec
= CALLOC_STRUCT(nvc0_decoder
);
202 dec
->client
= screen
->client
;
214 for (i
= 0; i
< 3; ++i
)
216 dec
->channel
[i
] = dec
->channel
[0];
217 dec
->pushbuf
[i
] = dec
->pushbuf
[0];
221 struct nvc0_fifo nvc0_args
= {};
222 struct nve0_fifo nve0_args
= {};
225 size
= sizeof(nvc0_args
);
228 unsigned engine
[] = {
229 NVE0_FIFO_ENGINE_BSP
,
234 nve0_args
.engine
= engine
[i
];
235 size
= sizeof(nve0_args
);
239 ret
= nouveau_object_new(&screen
->device
->object
, 0,
240 NOUVEAU_FIFO_CHANNEL_CLASS
,
241 data
, size
, &dec
->channel
[i
]);
244 ret
= nouveau_pushbuf_new(screen
->client
, dec
->channel
[i
], 4,
245 32 * 1024, true, &dec
->pushbuf
[i
]);
253 ret
= nouveau_object_new(dec
->channel
[0], 0x390b1, 0x90b1, NULL
, 0, &dec
->bsp
);
255 ret
= nouveau_object_new(dec
->channel
[1], 0x190b2, 0x90b2, NULL
, 0, &dec
->vp
);
257 ret
= nouveau_object_new(dec
->channel
[2], 0x290b3, 0x90b3, NULL
, 0, &dec
->ppp
);
260 ret
= nouveau_object_new(dec
->channel
[0], 0x95b1, 0x95b1, NULL
, 0, &dec
->bsp
);
262 ret
= nouveau_object_new(dec
->channel
[1], 0x95b2, 0x95b2, NULL
, 0, &dec
->vp
);
264 ret
= nouveau_object_new(dec
->channel
[2], 0x90b3, 0x90b3, NULL
, 0, &dec
->ppp
);
269 BEGIN_NVC0(push
[0], SUBC_BSP(NV01_SUBCHAN_OBJECT
), 1);
270 PUSH_DATA (push
[0], dec
->bsp
->handle
);
272 BEGIN_NVC0(push
[1], SUBC_VP(NV01_SUBCHAN_OBJECT
), 1);
273 PUSH_DATA (push
[1], dec
->vp
->handle
);
275 BEGIN_NVC0(push
[2], SUBC_PPP(NV01_SUBCHAN_OBJECT
), 1);
276 PUSH_DATA (push
[2], dec
->ppp
->handle
);
278 dec
->base
.context
= context
;
279 dec
->base
.profile
= profile
;
280 dec
->base
.entrypoint
= entrypoint
;
281 dec
->base
.chroma_format
= chroma_format
;
282 dec
->base
.width
= width
;
283 dec
->base
.height
= height
;
284 dec
->base
.max_references
= max_references
;
285 dec
->base
.destroy
= nvc0_decoder_destroy
;
286 dec
->base
.flush
= nvc0_decoder_flush
;
287 dec
->base
.decode_bitstream
= nvc0_decoder_decode_bitstream
;
288 dec
->base
.begin_frame
= nvc0_decoder_begin_frame
;
289 dec
->base
.end_frame
= nvc0_decoder_end_frame
;
291 for (i
= 0; i
< NVC0_VIDEO_QDEPTH
&& !ret
; ++i
)
292 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_VRAM
,
293 0, 1 << 20, &cfg
, &dec
->bsp_bo
[i
]);
295 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_VRAM
,
296 0x100, 4 << 20, &cfg
, &dec
->inter_bo
[0]);
299 nouveau_bo_ref(dec
->inter_bo
[0], &dec
->inter_bo
[1]);
301 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_VRAM
,
302 0x100, dec
->inter_bo
[0]->size
, &cfg
,
308 switch (u_reduce_video_profile(profile
)) {
309 case PIPE_VIDEO_CODEC_MPEG12
: {
311 assert(max_references
<= 2);
314 case PIPE_VIDEO_CODEC_MPEG4
: {
316 tmp_size
= mb(height
)*16 * mb(width
)*16;
317 assert(max_references
<= 2);
320 case PIPE_VIDEO_CODEC_VC1
: {
321 ppp_codec
= codec
= 2;
322 tmp_size
= mb(height
)*16 * mb(width
)*16;
323 assert(max_references
<= 2);
326 case PIPE_VIDEO_CODEC_MPEG4_AVC
: {
328 dec
->tmp_stride
= 16 * mb_half(width
) * nvc0_video_align(height
) * 3 / 2;
329 tmp_size
= dec
->tmp_stride
* (max_references
+ 1);
330 assert(max_references
<= 16);
334 fprintf(stderr
, "invalid codec\n");
338 if (screen
->device
->chipset
< 0xd0) {
342 uint32_t *end
, endval
;
344 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_VRAM
, 0,
345 0x4000, &cfg
, &dec
->fw_bo
);
347 ret
= nouveau_bo_map(dec
->fw_bo
, NOUVEAU_BO_WR
, dec
->client
);
351 nvc0_video_getpath(profile
, path
);
353 fd
= open(path
, O_RDONLY
| O_CLOEXEC
);
355 fprintf(stderr
, "opening firmware file %s failed: %m\n", path
);
358 r
= read(fd
, dec
->fw_bo
->map
, 0x4000);
360 fprintf(stderr
, "reading firmware file %s failed: %m\n", path
);
366 fprintf(stderr
, "firmware file %s too large!\n", path
);
372 fprintf(stderr
, "firmware file %s wrong size!\n", path
);
376 end
= dec
->fw_bo
->map
+ r
- 4;
378 while (endval
== *end
)
381 r
= (intptr_t)end
- (intptr_t)dec
->fw_bo
->map
+ 4;
383 switch (u_reduce_video_profile(profile
)) {
384 case PIPE_VIDEO_CODEC_MPEG12
: {
385 assert((r
& 0xff) == 0xe0);
386 dec
->fw_sizes
= (0x2e0<<16) | (r
- 0x2e0);
389 case PIPE_VIDEO_CODEC_MPEG4
: {
390 assert((r
& 0xff) == 0xe0);
391 dec
->fw_sizes
= (0x2e0<<16) | (r
- 0x2e0);
394 case PIPE_VIDEO_CODEC_VC1
: {
395 assert((r
& 0xff) == 0xac);
396 dec
->fw_sizes
= (0x3ac<<16) | (r
- 0x3ac);
399 case PIPE_VIDEO_CODEC_MPEG4_AVC
: {
400 assert((r
& 0xff) == 0x70);
401 dec
->fw_sizes
= (0x370<<16) | (r
- 0x370);
407 munmap(dec
->fw_bo
->map
, dec
->fw_bo
->size
);
408 dec
->fw_bo
->map
= NULL
;
412 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_VRAM
, 0,
413 0x400, &cfg
, &dec
->bitplane_bo
);
418 dec
->ref_stride
= mb(width
)*16 * (mb_half(height
)*32 + nvc0_video_align(height
)/2);
419 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_VRAM
, 0,
420 dec
->ref_stride
* (max_references
+2) + tmp_size
,
427 BEGIN_NVC0(push
[0], SUBC_BSP(0x200), 2);
428 PUSH_DATA (push
[0], codec
);
429 PUSH_DATA (push
[0], timeout
);
431 BEGIN_NVC0(push
[1], SUBC_VP(0x200), 2);
432 PUSH_DATA (push
[1], codec
);
433 PUSH_DATA (push
[1], timeout
);
435 BEGIN_NVC0(push
[2], SUBC_PPP(0x200), 2);
436 PUSH_DATA (push
[2], ppp_codec
);
437 PUSH_DATA (push
[2], timeout
);
442 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_GART
|NOUVEAU_BO_MAP
,
443 0, 0x1000, &cfg
, &dec
->fence_bo
);
447 nouveau_bo_map(dec
->fence_bo
, NOUVEAU_BO_RDWR
, screen
->client
);
448 dec
->fence_map
= dec
->fence_bo
->map
;
449 dec
->fence_map
[0] = dec
->fence_map
[4] = dec
->fence_map
[8] = 0;
450 dec
->comm
= (struct comm
*)(dec
->fence_map
+ (COMM_OFFSET
/sizeof(*dec
->fence_map
)));
452 /* So lets test if the fence is working? */
453 BEGIN_NVC0(push
[0], SUBC_BSP(0x240), 3);
454 PUSH_DATAh(push
[0], dec
->fence_bo
->offset
);
455 PUSH_DATA (push
[0], dec
->fence_bo
->offset
);
456 PUSH_DATA (push
[0], dec
->fence_seq
);
458 BEGIN_NVC0(push
[0], SUBC_BSP(0x304), 1);
459 PUSH_DATA (push
[0], 1);
462 BEGIN_NVC0(push
[1], SUBC_VP(0x240), 3);
463 PUSH_DATAh(push
[1], (dec
->fence_bo
->offset
+ 0x10));
464 PUSH_DATA (push
[1], (dec
->fence_bo
->offset
+ 0x10));
465 PUSH_DATA (push
[1], dec
->fence_seq
);
467 BEGIN_NVC0(push
[1], SUBC_VP(0x304), 1);
468 PUSH_DATA (push
[1], 1);
471 BEGIN_NVC0(push
[2], SUBC_PPP(0x240), 3);
472 PUSH_DATAh(push
[2], (dec
->fence_bo
->offset
+ 0x20));
473 PUSH_DATA (push
[2], (dec
->fence_bo
->offset
+ 0x20));
474 PUSH_DATA (push
[2], dec
->fence_seq
);
476 BEGIN_NVC0(push
[2], SUBC_PPP(0x304), 1);
477 PUSH_DATA (push
[2], 1);
481 while (dec
->fence_seq
> dec
->fence_map
[0] &&
482 dec
->fence_seq
> dec
->fence_map
[4] &&
483 dec
->fence_seq
> dec
->fence_map
[8]) {
484 debug_printf("%u: %u %u %u\n", dec
->fence_seq
, dec
->fence_map
[0], dec
->fence_map
[4], dec
->fence_map
[8]);
487 debug_printf("%u: %u %u %u\n", dec
->fence_seq
, dec
->fence_map
[0], dec
->fence_map
[4], dec
->fence_map
[8]);
493 debug_printf("Cannot create decoder without firmware..\n");
494 nvc0_decoder_destroy(&dec
->base
);
498 debug_printf("Creation failed: %s (%i)\n", strerror(-ret
), ret
);
499 nvc0_decoder_destroy(&dec
->base
);
503 static struct pipe_sampler_view
**
504 nvc0_video_buffer_sampler_view_planes(struct pipe_video_buffer
*buffer
)
506 struct nvc0_video_buffer
*buf
= (struct nvc0_video_buffer
*)buffer
;
507 return buf
->sampler_view_planes
;
510 static struct pipe_sampler_view
**
511 nvc0_video_buffer_sampler_view_components(struct pipe_video_buffer
*buffer
)
513 struct nvc0_video_buffer
*buf
= (struct nvc0_video_buffer
*)buffer
;
514 return buf
->sampler_view_components
;
517 static struct pipe_surface
**
518 nvc0_video_buffer_surfaces(struct pipe_video_buffer
*buffer
)
520 struct nvc0_video_buffer
*buf
= (struct nvc0_video_buffer
*)buffer
;
521 return buf
->surfaces
;
525 nvc0_video_buffer_destroy(struct pipe_video_buffer
*buffer
)
527 struct nvc0_video_buffer
*buf
= (struct nvc0_video_buffer
*)buffer
;
532 for (i
= 0; i
< VL_NUM_COMPONENTS
; ++i
) {
533 pipe_resource_reference(&buf
->resources
[i
], NULL
);
534 pipe_sampler_view_reference(&buf
->sampler_view_planes
[i
], NULL
);
535 pipe_sampler_view_reference(&buf
->sampler_view_components
[i
], NULL
);
536 pipe_surface_reference(&buf
->surfaces
[i
* 2], NULL
);
537 pipe_surface_reference(&buf
->surfaces
[i
* 2 + 1], NULL
);
542 struct pipe_video_buffer
*
543 nvc0_video_buffer_create(struct pipe_context
*pipe
,
544 const struct pipe_video_buffer
*templat
)
546 struct nvc0_video_buffer
*buffer
;
547 struct pipe_resource templ
;
548 unsigned i
, j
, component
;
549 struct pipe_sampler_view sv_templ
;
550 struct pipe_surface surf_templ
;
552 assert(templat
->interlaced
);
553 if (getenv("XVMC_VL") || templat
->buffer_format
!= PIPE_FORMAT_NV12
)
554 return vl_video_buffer_create(pipe
, templat
);
556 assert(templat
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
558 buffer
= CALLOC_STRUCT(nvc0_video_buffer
);
561 assert(!(templat
->height
% 4));
562 assert(!(templat
->width
% 2));
564 buffer
->base
.buffer_format
= templat
->buffer_format
;
565 buffer
->base
.context
= pipe
;
566 buffer
->base
.destroy
= nvc0_video_buffer_destroy
;
567 buffer
->base
.chroma_format
= templat
->chroma_format
;
568 buffer
->base
.width
= templat
->width
;
569 buffer
->base
.height
= templat
->height
;
570 buffer
->base
.get_sampler_view_planes
= nvc0_video_buffer_sampler_view_planes
;
571 buffer
->base
.get_sampler_view_components
= nvc0_video_buffer_sampler_view_components
;
572 buffer
->base
.get_surfaces
= nvc0_video_buffer_surfaces
;
573 buffer
->base
.interlaced
= true;
575 memset(&templ
, 0, sizeof(templ
));
576 templ
.target
= PIPE_TEXTURE_3D
;
578 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
579 templ
.format
= PIPE_FORMAT_R8_UNORM
;
580 templ
.width0
= buffer
->base
.width
;
581 templ
.height0
= buffer
->base
.height
/2;
582 templ
.flags
= NVC0_RESOURCE_FLAG_VIDEO
;
583 templ
.last_level
= 0;
584 templ
.array_size
= 1;
586 buffer
->resources
[0] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
587 if (!buffer
->resources
[0])
590 templ
.format
= PIPE_FORMAT_R8G8_UNORM
;
591 buffer
->num_planes
= 2;
594 for (i
= 1; i
< buffer
->num_planes
; ++i
) {
595 buffer
->resources
[i
] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
596 if (!buffer
->resources
[i
])
600 memset(&sv_templ
, 0, sizeof(sv_templ
));
601 for (component
= 0, i
= 0; i
< buffer
->num_planes
; ++i
) {
602 struct pipe_resource
*res
= buffer
->resources
[i
];
603 unsigned nr_components
= util_format_get_nr_components(res
->format
);
605 u_sampler_view_default_template(&sv_templ
, res
, res
->format
);
606 buffer
->sampler_view_planes
[i
] = pipe
->create_sampler_view(pipe
, res
, &sv_templ
);
607 if (!buffer
->sampler_view_planes
[i
])
610 for (j
= 0; j
< nr_components
; ++j
, ++component
) {
611 sv_templ
.swizzle_r
= sv_templ
.swizzle_g
= sv_templ
.swizzle_b
= PIPE_SWIZZLE_RED
+ j
;
612 sv_templ
.swizzle_a
= PIPE_SWIZZLE_ONE
;
614 buffer
->sampler_view_components
[component
] = pipe
->create_sampler_view(pipe
, res
, &sv_templ
);
615 if (!buffer
->sampler_view_components
[component
])
620 memset(&surf_templ
, 0, sizeof(surf_templ
));
621 for (j
= 0; j
< buffer
->num_planes
; ++j
) {
622 surf_templ
.format
= buffer
->resources
[j
]->format
;
623 surf_templ
.u
.tex
.first_layer
= surf_templ
.u
.tex
.last_layer
= 0;
624 buffer
->surfaces
[j
* 2] = pipe
->create_surface(pipe
, buffer
->resources
[j
], &surf_templ
);
625 if (!buffer
->surfaces
[j
* 2])
628 surf_templ
.u
.tex
.first_layer
= surf_templ
.u
.tex
.last_layer
= 1;
629 buffer
->surfaces
[j
* 2 + 1] = pipe
->create_surface(pipe
, buffer
->resources
[j
], &surf_templ
);
630 if (!buffer
->surfaces
[j
* 2 + 1])
634 return &buffer
->base
;
637 nvc0_video_buffer_destroy(&buffer
->base
);