2 * Copyright 2013 Ilia Mirkin
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 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.
25 #include <sys/types.h>
28 #include "util/u_format.h"
29 #include "util/u_sampler.h"
30 #include "vl/vl_zscan.h"
32 #include "nv50/nv84_video.h"
35 nv84_copy_firmware(const char *path
, void *dest
, ssize_t len
)
37 int fd
= open(path
, O_RDONLY
| O_CLOEXEC
);
40 fprintf(stderr
, "opening firmware file %s failed: %m\n", path
);
43 r
= read(fd
, dest
, len
);
47 fprintf(stderr
, "reading firwmare file %s failed: %m\n", path
);
55 filesize(const char *path
)
60 ret
= stat(path
, &statbuf
);
63 return statbuf
.st_size
;
66 static struct nouveau_bo
*
67 nv84_load_firmwares(struct nouveau_device
*dev
, struct nv84_decoder
*dec
,
68 const char *fw1
, const char *fw2
)
70 int ret
, size1
, size2
= 0;
71 struct nouveau_bo
*fw
;
73 size1
= filesize(fw1
);
75 size2
= filesize(fw2
);
76 if (size1
< 0 || size2
< 0)
79 dec
->vp_fw2_offset
= align(size1
, 0x100);
81 ret
= nouveau_bo_new(dev
, NOUVEAU_BO_VRAM
, 0, dec
->vp_fw2_offset
+ size2
, NULL
, &fw
);
84 ret
= nouveau_bo_map(fw
, NOUVEAU_BO_WR
, dec
->client
);
88 ret
= nv84_copy_firmware(fw1
, fw
->map
, size1
);
90 ret
= nv84_copy_firmware(fw2
, fw
->map
+ dec
->vp_fw2_offset
, size2
);
91 munmap(fw
->map
, fw
->size
);
96 nouveau_bo_ref(NULL
, &fw
);
100 static struct nouveau_bo
*
101 nv84_load_bsp_firmware(struct nouveau_device
*dev
, struct nv84_decoder
*dec
)
103 return nv84_load_firmwares(
104 dev
, dec
, "/lib/firmware/nouveau/nv84_bsp-h264", NULL
);
107 static struct nouveau_bo
*
108 nv84_load_vp_firmware(struct nouveau_device
*dev
, struct nv84_decoder
*dec
)
110 return nv84_load_firmwares(
112 "/lib/firmware/nouveau/nv84_vp-h264-1",
113 "/lib/firmware/nouveau/nv84_vp-h264-2");
116 static struct nouveau_bo
*
117 nv84_load_vp_firmware_mpeg(struct nouveau_device
*dev
, struct nv84_decoder
*dec
)
119 return nv84_load_firmwares(
120 dev
, dec
, "/lib/firmware/nouveau/nv84_vp-mpeg12", NULL
);
124 nv84_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
)
131 struct nv84_decoder
*dec
= (struct nv84_decoder
*)decoder
;
132 struct nv84_video_buffer
*target
= (struct nv84_video_buffer
*)video_target
;
134 struct pipe_h264_picture_desc
*desc
= (struct pipe_h264_picture_desc
*)picture
;
136 assert(target
->base
.buffer_format
== PIPE_FORMAT_NV12
);
138 nv84_decoder_bsp(dec
, desc
, num_buffers
, data
, num_bytes
, target
);
139 nv84_decoder_vp_h264(dec
, desc
, target
);
143 nv84_decoder_flush(struct pipe_video_codec
*decoder
)
148 nv84_decoder_begin_frame_h264(struct pipe_video_codec
*decoder
,
149 struct pipe_video_buffer
*target
,
150 struct pipe_picture_desc
*picture
)
155 nv84_decoder_end_frame_h264(struct pipe_video_codec
*decoder
,
156 struct pipe_video_buffer
*target
,
157 struct pipe_picture_desc
*picture
)
162 nv84_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
)
169 struct nv84_decoder
*dec
= (struct nv84_decoder
*)decoder
;
171 assert(video_target
->buffer_format
== PIPE_FORMAT_NV12
);
173 vl_mpg12_bs_decode(dec
->mpeg12_bs
,
175 (struct pipe_mpeg12_picture_desc
*)picture
,
182 nv84_decoder_begin_frame_mpeg12(struct pipe_video_codec
*decoder
,
183 struct pipe_video_buffer
*target
,
184 struct pipe_picture_desc
*picture
)
186 struct nv84_decoder
*dec
= (struct nv84_decoder
*)decoder
;
187 struct pipe_mpeg12_picture_desc
*desc
= (struct pipe_mpeg12_picture_desc
*)picture
;
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
]];
200 dec
->mpeg12_intra_matrix
[0] = 1 << (7 - desc
->intra_dc_precision
);
205 nv84_decoder_end_frame_mpeg12(struct pipe_video_codec
*decoder
,
206 struct pipe_video_buffer
*target
,
207 struct pipe_picture_desc
*picture
)
209 nv84_decoder_vp_mpeg12(
210 (struct nv84_decoder
*)decoder
,
211 (struct pipe_mpeg12_picture_desc
*)picture
,
212 (struct nv84_video_buffer
*)target
);
216 nv84_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
)
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
,
232 nv84_decoder_destroy(struct pipe_video_codec
*decoder
)
234 struct nv84_decoder
*dec
= (struct nv84_decoder
*)decoder
;
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
);
246 nouveau_object_del(&dec
->bsp
);
247 nouveau_object_del(&dec
->vp
);
249 nouveau_bufctx_del(&dec
->bsp_bufctx
);
250 nouveau_pushbuf_del(&dec
->bsp_pushbuf
);
251 nouveau_object_del(&dec
->bsp_channel
);
253 nouveau_bufctx_del(&dec
->vp_bufctx
);
254 nouveau_pushbuf_del(&dec
->vp_pushbuf
);
255 nouveau_object_del(&dec
->vp_channel
);
257 nouveau_client_del(&dec
->client
);
259 FREE(dec
->mpeg12_bs
);
263 struct pipe_video_codec
*
264 nv84_create_decoder(struct pipe_context
*context
,
265 const struct pipe_video_codec
*templ
)
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 };
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
;
279 if (getenv("XVMC_VL"))
280 return vl_create_decoder(context
, templ
);
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
);
288 if (!is_h264
&& !is_mpeg12
) {
289 debug_printf("invalid profile: %x\n", templ
->profile
);
293 dec
= CALLOC_STRUCT(nv84_decoder
);
298 dec
->base
.context
= context
;
299 dec
->base
.destroy
= nv84_decoder_destroy
;
300 dec
->base
.flush
= nv84_decoder_flush
;
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
;
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
;
316 if (templ
->entrypoint
== PIPE_VIDEO_ENTRYPOINT_BITSTREAM
) {
317 dec
->mpeg12_bs
= CALLOC_STRUCT(vl_mpg12_bs
);
320 vl_mpg12_bs_init(dec
->mpeg12_bs
, &dec
->base
);
321 dec
->base
.decode_bitstream
= nv84_decoder_decode_bitstream_mpeg12
;
327 ret
= nouveau_client_new(screen
->device
, &dec
->client
);
332 ret
= nouveau_object_new(&screen
->device
->object
, 0,
333 NOUVEAU_FIFO_CHANNEL_CLASS
,
334 &nv04_data
, sizeof(nv04_data
), &dec
->bsp_channel
);
338 ret
= nouveau_pushbuf_new(dec
->client
, dec
->bsp_channel
, 4,
339 32 * 1024, true, &dec
->bsp_pushbuf
);
343 ret
= nouveau_bufctx_new(dec
->client
, 1, &dec
->bsp_bufctx
);
348 ret
= nouveau_object_new(&screen
->device
->object
, 0,
349 NOUVEAU_FIFO_CHANNEL_CLASS
,
350 &nv04_data
, sizeof(nv04_data
), &dec
->vp_channel
);
353 ret
= nouveau_pushbuf_new(dec
->client
, dec
->vp_channel
, 4,
354 32 * 1024, true, &dec
->vp_pushbuf
);
358 ret
= nouveau_bufctx_new(dec
->client
, 1, &dec
->vp_bufctx
);
362 bsp_push
= dec
->bsp_pushbuf
;
363 vp_push
= dec
->vp_pushbuf
;
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
)
372 dec
->vp_fw
= nv84_load_vp_firmware_mpeg(screen
->device
, dec
);
378 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_NOSNOOP
,
379 0, 0x40000, NULL
, &dec
->bsp_data
);
383 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_NOSNOOP
,
384 0, 0x40000, NULL
, &dec
->vp_data
);
388 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_NOSNOOP
,
390 2 * (dec
->vpring_deblock
+
391 dec
->vpring_residual
+
397 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_NOSNOOP
,
399 (templ
->max_references
+ 1) * dec
->frame_mbs
* 0x40 +
400 dec
->frame_size
+ 0x2000,
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
);
409 ret
= nouveau_bo_map(dec
->bitstream
, NOUVEAU_BO_WR
, dec
->client
);
412 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_GART
,
413 0, 0x2000, NULL
, &dec
->vp_params
);
416 ret
= nouveau_bo_map(dec
->vp_params
, NOUVEAU_BO_WR
, dec
->client
);
421 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_GART
,
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
);
428 ret
= nouveau_bo_map(dec
->mpeg12_bo
, NOUVEAU_BO_WR
, dec
->client
);
433 ret
= nouveau_bo_new(screen
->device
, NOUVEAU_BO_VRAM
,
434 0, 0x1000, NULL
, &dec
->fence
);
437 ret
= nouveau_bo_map(dec
->fence
, NOUVEAU_BO_WR
, dec
->client
);
440 *(uint32_t *)dec
->fence
->map
= 0;
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
);
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
);
457 ret
= nouveau_object_new(dec
->bsp_channel
, 0xbeef74b0, 0x74b0,
461 ret
= nouveau_object_new(dec
->vp_channel
, 0xbeef7476, 0x7476,
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
472 color
.f
[0] = color
.f
[1] = color
.f
[2] = color
.f
[3] = 0;
473 surf
.offset
= dec
->frame_size
;
475 surf
.height
= (templ
->max_references
+ 1) * dec
->frame_mbs
/ 4;
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;
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);
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.
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
);
508 PUSH_SPACE(bsp_push
, 2 + 12 + 2 + 4 + 3);
510 BEGIN_NV04(bsp_push
, SUBC_BSP(NV01_SUBCHAN_OBJECT
), 1);
511 PUSH_DATA (bsp_push
, dec
->bsp
->handle
);
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
);
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
);
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
);
530 PUSH_SPACE(vp_push
, 2 + 12 + 2 + 4 + 3);
532 BEGIN_NV04(vp_push
, SUBC_VP(NV01_SUBCHAN_OBJECT
), 1);
533 PUSH_DATA (vp_push
, dec
->vp
->handle
);
535 BEGIN_NV04(vp_push
, SUBC_VP(0x180), 11);
536 for (i
= 0; i
< 11; i
++)
537 PUSH_DATA(vp_push
, nv04_data
.vram
);
539 BEGIN_NV04(vp_push
, SUBC_VP(0x1b8), 1);
540 PUSH_DATA (vp_push
, nv04_data
.vram
);
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
);
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
);
554 nv84_decoder_destroy(&dec
->base
);
558 static struct pipe_sampler_view
**
559 nv84_video_buffer_sampler_view_planes(struct pipe_video_buffer
*buffer
)
561 struct nv84_video_buffer
*buf
= (struct nv84_video_buffer
*)buffer
;
562 return buf
->sampler_view_planes
;
565 static struct pipe_sampler_view
**
566 nv84_video_buffer_sampler_view_components(struct pipe_video_buffer
*buffer
)
568 struct nv84_video_buffer
*buf
= (struct nv84_video_buffer
*)buffer
;
569 return buf
->sampler_view_components
;
572 static struct pipe_surface
**
573 nv84_video_buffer_surfaces(struct pipe_video_buffer
*buffer
)
575 struct nv84_video_buffer
*buf
= (struct nv84_video_buffer
*)buffer
;
576 return buf
->surfaces
;
580 nv84_video_buffer_destroy(struct pipe_video_buffer
*buffer
)
582 struct nv84_video_buffer
*buf
= (struct nv84_video_buffer
*)buffer
;
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
);
595 nouveau_bo_ref(NULL
, &buf
->interlaced
);
596 nouveau_bo_ref(NULL
, &buf
->full
);
601 struct pipe_video_buffer
*
602 nv84_video_buffer_create(struct pipe_context
*pipe
,
603 const struct pipe_video_buffer
*template)
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
;
615 if (getenv("XVMC_VL") || template->buffer_format
!= PIPE_FORMAT_NV12
)
616 return vl_video_buffer_create(pipe
, template);
618 if (!template->interlaced
) {
619 debug_printf("Require interlaced video buffers\n");
622 if (template->chroma_format
!= PIPE_VIDEO_CHROMA_FORMAT_420
) {
623 debug_printf("Must use 4:2:0 format\n");
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.
633 buffer
= CALLOC_STRUCT(nv84_video_buffer
);
634 if (!buffer
) return NULL
;
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;
649 memset(&templ
, 0, sizeof(templ
));
650 templ
.target
= PIPE_TEXTURE_2D_ARRAY
;
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;
659 cfg
.nv50
.tile_mode
= 0x20;
660 cfg
.nv50
.memtype
= 0x70;
662 buffer
->resources
[0] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
663 if (!buffer
->resources
[0])
666 templ
.format
= PIPE_FORMAT_R8G8_UNORM
;
669 buffer
->resources
[1] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
670 if (!buffer
->resources
[1])
673 mt0
= nv50_miptree(buffer
->resources
[0]);
674 mt1
= nv50_miptree(buffer
->resources
[1]);
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
))
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
))
686 nouveau_bo_ref(buffer
->interlaced
, &mt0
->base
.bo
);
687 mt0
->base
.domain
= NOUVEAU_BO_VRAM
;
688 mt0
->base
.address
= buffer
->interlaced
->offset
;
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
;
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
);
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
])
706 for (j
= 0; j
< nr_components
; ++j
, ++component
) {
707 sv_templ
.swizzle_r
= sv_templ
.swizzle_g
= sv_templ
.swizzle_b
=
709 sv_templ
.swizzle_a
= PIPE_SWIZZLE_1
;
711 buffer
->sampler_view_components
[component
] =
712 pipe
->create_sampler_view(pipe
, res
, &sv_templ
);
713 if (!buffer
->sampler_view_components
[component
])
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])
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])
734 return &buffer
->base
;
737 nv84_video_buffer_destroy(&buffer
->base
);
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)
750 firmware_present(struct pipe_screen
*pscreen
, enum pipe_video_format codec
)
752 struct nouveau_screen
*screen
= nouveau_screen(pscreen
);
753 struct nouveau_object
*obj
= NULL
;
755 int checked
= screen
->firmware_info
.profiles_checked
;
758 if (!FIRMWARE_PRESENT(checked
, VP_KERN
)) {
759 ret
= nouveau_object_new(screen
->channel
, 0, 0x7476, NULL
, 0, &obj
);
761 screen
->firmware_info
.profiles_present
|= FIRMWARE_VP_KERN
;
762 nouveau_object_del(&obj
);
763 screen
->firmware_info
.profiles_checked
|= FIRMWARE_VP_KERN
;
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
);
770 screen
->firmware_info
.profiles_present
|= FIRMWARE_BSP_KERN
;
771 nouveau_object_del(&obj
);
772 screen
->firmware_info
.profiles_checked
|= FIRMWARE_BSP_KERN
;
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
;
782 /* should probably check the others, but assume that 1 means all */
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
);
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
;
795 present
= screen
->firmware_info
.profiles_present
;
796 return FIRMWARE_PRESENT(present
, VP_KERN
) &&
797 FIRMWARE_PRESENT(present
, VP_MPEG2
);
802 nv84_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
)
807 enum pipe_video_format codec
;
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
:
817 case PIPE_VIDEO_CAP_MAX_WIDTH
:
818 case PIPE_VIDEO_CAP_MAX_HEIGHT
:
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
:
825 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE
:
827 case PIPE_VIDEO_CAP_MAX_LEVEL
:
829 case PIPE_VIDEO_PROFILE_MPEG1
:
831 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE
:
832 case PIPE_VIDEO_PROFILE_MPEG2_MAIN
:
834 case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE
:
835 case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN
:
836 case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
:
839 debug_printf("unknown video profile: %d\n", profile
);
843 debug_printf("unknown video param: %d\n", param
);
849 nv84_screen_video_supported(struct pipe_screen
*screen
,
850 enum pipe_format format
,
851 enum pipe_video_profile profile
,
852 enum pipe_video_entrypoint entrypoint
)
854 if (profile
!= PIPE_VIDEO_PROFILE_UNKNOWN
)
855 return format
== PIPE_FORMAT_NV12
;
857 return vl_video_buffer_is_format_supported(screen
, format
, profile
, entrypoint
);