2 * Copyright 2011 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 "vl/vl_decoder.h"
24 #include "vl/vl_video_buffer.h"
26 #include "nouveau_screen.h"
27 #include "nouveau_context.h"
28 #include "nouveau_video.h"
30 #include "nouveau/nouveau_buffer.h"
31 #include "util/u_video.h"
32 #include "util/u_format.h"
33 #include "util/u_sampler.h"
36 nouveau_vpe_init(struct nouveau_decoder
*dec
) {
40 ret
= nouveau_bo_map(dec
->cmd_bo
, NOUVEAU_BO_RDWR
, dec
->client
);
42 debug_printf("Mapping cmd bo: %s\n", strerror(-ret
));
45 ret
= nouveau_bo_map(dec
->data_bo
, NOUVEAU_BO_RDWR
, dec
->client
);
47 debug_printf("Mapping data bo: %s\n", strerror(-ret
));
50 dec
->cmds
= dec
->cmd_bo
->map
;
51 dec
->data
= dec
->data_bo
->map
;
56 nouveau_vpe_synch(struct nouveau_decoder
*dec
) {
57 struct nouveau_pushbuf
*push
= dec
->push
;
60 BEGIN_NV04(push
, NV84_MPEG(QUERY_COUNTER
), 1);
61 PUSH_DATA (push
, ++dec
->fence_seq
);
63 while (dec
->fence_map
[0] != dec
->fence_seq
)
71 nouveau_vpe_fini(struct nouveau_decoder
*dec
) {
72 struct nouveau_pushbuf
*push
= dec
->push
;
76 nouveau_pushbuf_space(push
, 8, 2, 0);
77 nouveau_bufctx_reset(dec
->bufctx
, NV31_VIDEO_BIND_CMD
);
79 #define BCTX_ARGS dec->bufctx, NV31_VIDEO_BIND_CMD, NOUVEAU_BO_RD
81 BEGIN_NV04(push
, NV31_MPEG(CMD_OFFSET
), 2);
82 PUSH_MTHDl(push
, NV31_MPEG(CMD_OFFSET
), dec
->cmd_bo
, 0, BCTX_ARGS
);
83 PUSH_DATA (push
, dec
->ofs
* 4);
85 BEGIN_NV04(push
, NV31_MPEG(DATA_OFFSET
), 2);
86 PUSH_MTHDl(push
, NV31_MPEG(DATA_OFFSET
), dec
->data_bo
, 0, BCTX_ARGS
);
87 PUSH_DATA (push
, dec
->data_pos
* 4);
91 if (unlikely(nouveau_pushbuf_validate(dec
->push
)))
94 BEGIN_NV04(push
, NV31_MPEG(EXEC
), 1);
97 nouveau_vpe_synch(dec
);
98 dec
->ofs
= dec
->data_pos
= dec
->num_surfaces
= 0;
99 dec
->cmds
= dec
->data
= NULL
;
100 dec
->current
= dec
->future
= dec
->past
= 8;
104 nouveau_vpe_mb_dct_blocks(struct nouveau_decoder
*dec
, const struct pipe_mpeg12_macroblock
*mb
)
107 unsigned cbp
= mb
->coded_block_pattern
;
108 short *db
= mb
->blocks
;
109 for (cbb
= 0x20; cbb
> 0; cbb
>>= 1) {
111 static const int lookup
[64] = {
112 0, 1, 8,16, 9, 2, 3,10,
113 17,24,32,25,18,11, 4, 5,
114 12,19,26,33,40,48,41,34,
115 27,20,13, 6, 7,14,21,28,
116 35,42,49,56,57,50,43,36,
117 29,22,15,23,30,37,44,51,
118 58,59,52,45,38,31,39,46,
119 53,60,61,54,47,55,62,63
121 int i
, j
= 0, found
= 0;
122 for (i
= 0; i
< 64; ++i
) {
123 if (!db
[lookup
[i
]]) { j
+= 2; continue; }
124 dec
->data
[dec
->data_pos
++] = (db
[lookup
[i
]] << 16) | j
;
129 dec
->data
[dec
->data_pos
- 1] |= 1;
131 dec
->data
[dec
->data_pos
++] = 1;
133 } else if (mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
) {
134 dec
->data
[dec
->data_pos
++] = 1;
140 nouveau_vpe_mb_data_blocks(struct nouveau_decoder
*dec
, const struct pipe_mpeg12_macroblock
*mb
)
143 unsigned cbp
= mb
->coded_block_pattern
;
144 short *db
= mb
->blocks
;
145 for (cbb
= 0x20; cbb
> 0; cbb
>>= 1) {
147 memcpy(&dec
->data
[dec
->data_pos
], db
, 128);
150 } else if (mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
) {
151 memset(&dec
->data
[dec
->data_pos
], 0, 128);
158 nouveau_vpe_mb_dct_header(struct nouveau_decoder
*dec
,
159 const struct pipe_mpeg12_macroblock
*mb
,
162 unsigned base_dct
, cbp
;
163 bool intra
= mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
;
164 unsigned x
= mb
->x
* 16;
165 unsigned y
= luma
? mb
->y
* 16 : mb
->y
* 8;
167 /* Setup the base dct header */
168 base_dct
= dec
->current
<< NV17_MPEG_CMD_CHROMA_MB_HEADER_SURFACE__SHIFT
;
169 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_RUN_SINGLE
;
172 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_X_COORD_EVEN
;
176 cbp
= mb
->coded_block_pattern
;
178 if (dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FRAME
) {
179 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_TYPE_FRAME
;
180 if (luma
&& mb
->macroblock_modes
.bits
.dct_type
== PIPE_MPEG12_DCT_TYPE_FIELD
)
181 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_FRAME_DCT_TYPE_FIELD
;
183 if (dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_BOTTOM
)
184 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_FIELD_BOTTOM
;
190 base_dct
|= NV17_MPEG_CMD_LUMA_MB_HEADER_OP_LUMA_MB_HEADER
;
191 base_dct
|= (cbp
>> 2) << NV17_MPEG_CMD_LUMA_MB_HEADER_CBP__SHIFT
;
193 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_OP_CHROMA_MB_HEADER
;
194 base_dct
|= (cbp
& 3) << NV17_MPEG_CMD_CHROMA_MB_HEADER_CBP__SHIFT
;
196 nouveau_vpe_write(dec
, base_dct
);
197 nouveau_vpe_write(dec
, NV17_MPEG_CMD_MB_COORDS_OP_MB_COORDS
|
198 x
| (y
<< NV17_MPEG_CMD_MB_COORDS_Y__SHIFT
));
201 static INLINE
unsigned int
202 nouveau_vpe_mb_mv_flags(bool luma
, int mv_h
, int mv_v
, bool forward
, bool first
, bool vert
)
204 unsigned mc_header
= 0;
206 mc_header
|= NV17_MPEG_CMD_LUMA_MV_HEADER_OP_LUMA_MV_HEADER
;
208 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_OP_CHROMA_MV_HEADER
;
210 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_X_HALF
;
212 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_Y_HALF
;
214 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_DIRECTION_BACKWARD
;
216 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_IDX
;
218 mc_header
|= NV17_MPEG_CMD_LUMA_MV_HEADER_FIELD_BOTTOM
;
222 static unsigned pos(int pos
, int mov
, int max
) {
231 /* because we want -1 / 2 = -1 */
232 static int div_down(int val
, int mult
) {
237 static int div_up(int val
, int mult
) {
243 nouveau_vpe_mb_mv(struct nouveau_decoder
*dec
, unsigned mc_header
,
244 bool luma
, bool frame
, bool forward
, bool vert
,
245 int x
, int y
, const short motions
[2],
246 unsigned surface
, bool first
)
249 int mv_horizontal
= motions
[0];
250 int mv_vertical
= motions
[1];
251 int mv2
= mc_header
& NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2
;
252 unsigned width
= dec
->base
.width
;
253 unsigned height
= dec
->base
.height
;
255 mv_vertical
= div_down(mv_vertical
, 2);
256 assert(frame
); // Untested for non-frames
260 mc_header
|= surface
<< NV17_MPEG_CMD_CHROMA_MV_HEADER_SURFACE__SHIFT
;
262 mv_vertical
= div_up(mv_vertical
, 2);
263 mv_horizontal
= div_up(mv_horizontal
, 2);
266 mc_header
|= nouveau_vpe_mb_mv_flags(luma
, mv_horizontal
, mv_vertical
, forward
, first
, vert
);
267 nouveau_vpe_write(dec
, mc_header
);
269 mc_vector
= NV17_MPEG_CMD_MV_COORDS_OP_MV_COORDS
;
271 mc_vector
|= pos(x
, div_down(mv_horizontal
, 2), width
);
273 mc_vector
|= pos(x
, mv_horizontal
& ~1, width
);
275 mc_vector
|= pos(y
, div_down(mv_vertical
, 2), height
) << NV17_MPEG_CMD_MV_COORDS_Y__SHIFT
;
277 mc_vector
|= pos(y
, mv_vertical
& ~1, height
) << NV17_MPEG_CMD_MV_COORDS_Y__SHIFT
;
278 nouveau_vpe_write(dec
, mc_vector
);
282 nouveau_vpe_mb_mv_header(struct nouveau_decoder
*dec
,
283 const struct pipe_mpeg12_macroblock
*mb
,
286 bool frame
= dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FRAME
;
288 bool forward
, backward
;
289 int y
, y2
, x
= mb
->x
* 16;
291 y
= mb
->y
* (frame
? 16 : 32);
293 y
= mb
->y
* (frame
? 8 : 16);
297 y2
= y
+ (luma
? 16 : 8);
299 forward
= mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_MOTION_FORWARD
;
300 backward
= mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD
;
301 assert(!forward
|| dec
->past
< 8);
302 assert(!backward
|| dec
->future
< 8);
304 switch (mb
->macroblock_modes
.bits
.frame_motion_type
) {
305 case PIPE_MPEG12_MO_TYPE_FRAME
: goto mv1
;
306 case PIPE_MPEG12_MO_TYPE_FIELD
: goto mv2
;
307 case PIPE_MPEG12_MO_TYPE_DUAL_PRIME
: {
308 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2
;
310 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
, FALSE
,
311 x
, y
, mb
->PMV
[0][0], dec
->past
, TRUE
);
312 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
, TRUE
,
313 x
, y2
, mb
->PMV
[0][0], dec
->past
, FALSE
);
315 if (backward
&& forward
) {
316 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
, TRUE
,
317 x
, y
, mb
->PMV
[1][0], dec
->future
, TRUE
);
318 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
, FALSE
,
319 x
, y2
, mb
->PMV
[1][1], dec
->future
, FALSE
);
320 } else assert(!backward
);
326 switch (mb
->macroblock_modes
.bits
.field_motion_type
) {
327 case PIPE_MPEG12_MO_TYPE_FIELD
: goto mv1
;
328 case PIPE_MPEG12_MO_TYPE_16x8
: goto mv2
;
329 case PIPE_MPEG12_MO_TYPE_DUAL_PRIME
: {
330 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB
;
332 base
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_TYPE_FRAME
;
334 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
,
335 dec
->picture_structure
!= PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_TOP
,
336 x
, y
, mb
->PMV
[0][0], dec
->past
, TRUE
);
337 if (backward
&& forward
)
338 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, FALSE
,
339 dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_TOP
,
340 x
, y
, mb
->PMV
[0][1], dec
->future
, TRUE
);
341 else assert(!backward
);
350 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB
;
352 base
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_TYPE_FRAME
;
355 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
, FALSE
,
356 x
, y
, mb
->PMV
[0][0], dec
->past
, TRUE
);
358 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
, FALSE
,
359 x
, y
, mb
->PMV
[0][1], dec
->future
, TRUE
);
363 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2
;
365 base
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB
;
367 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
,
368 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_FIRST_FORWARD
,
369 x
, y
, mb
->PMV
[0][0], dec
->past
, TRUE
);
370 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
,
371 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_SECOND_FORWARD
,
372 x
, y2
, mb
->PMV
[1][0], dec
->past
, FALSE
);
375 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
,
376 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_FIRST_BACKWARD
,
377 x
, y
, mb
->PMV
[0][1], dec
->future
, TRUE
);
378 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
,
379 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_SECOND_BACKWARD
,
380 x
, y2
, mb
->PMV
[1][1], dec
->future
, FALSE
);
385 nouveau_decoder_surface_index(struct nouveau_decoder
*dec
,
386 struct pipe_video_buffer
*buffer
)
388 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
389 struct nouveau_pushbuf
*push
= dec
->push
;
390 struct nouveau_bo
*bo_y
= nv04_resource(buf
->resources
[0])->bo
;
391 struct nouveau_bo
*bo_c
= nv04_resource(buf
->resources
[1])->bo
;
397 for (i
= 0; i
< dec
->num_surfaces
; ++i
) {
398 if (dec
->surfaces
[i
] == buf
)
402 dec
->surfaces
[i
] = buf
;
405 nouveau_bufctx_reset(dec
->bufctx
, NV31_VIDEO_BIND_IMG(i
));
407 #define BCTX_ARGS dec->bufctx, NV31_VIDEO_BIND_IMG(i), NOUVEAU_BO_RDWR
408 BEGIN_NV04(push
, NV31_MPEG(IMAGE_Y_OFFSET(i
)), 2);
409 PUSH_MTHDl(push
, NV31_MPEG(IMAGE_Y_OFFSET(i
)), bo_y
, 0, BCTX_ARGS
);
410 PUSH_MTHDl(push
, NV31_MPEG(IMAGE_C_OFFSET(i
)), bo_c
, 0, BCTX_ARGS
);
417 nouveau_decoder_begin_frame(struct pipe_video_decoder
*decoder
,
418 struct pipe_video_buffer
*target
,
419 struct pipe_picture_desc
*picture
)
424 nouveau_decoder_decode_macroblock(struct pipe_video_decoder
*decoder
,
425 struct pipe_video_buffer
*target
,
426 struct pipe_picture_desc
*picture
,
427 const struct pipe_macroblock
*pipe_mb
,
428 unsigned num_macroblocks
)
430 struct nouveau_decoder
*dec
= (struct nouveau_decoder
*)decoder
;
431 struct pipe_mpeg12_picture_desc
*desc
= (struct pipe_mpeg12_picture_desc
*)picture
;
432 const struct pipe_mpeg12_macroblock
*mb
;
434 assert(target
->width
== decoder
->width
);
435 assert(target
->height
== decoder
->height
);
437 dec
->current
= nouveau_decoder_surface_index(dec
, target
);
438 assert(dec
->current
< 8);
439 dec
->picture_structure
= desc
->picture_structure
;
441 dec
->future
= nouveau_decoder_surface_index(dec
, desc
->ref
[1]);
443 dec
->past
= nouveau_decoder_surface_index(dec
, desc
->ref
[0]);
445 if (nouveau_vpe_init(dec
)) return;
446 mb
= (const struct pipe_mpeg12_macroblock
*)pipe_mb
;
447 for (i
= 0; i
< num_macroblocks
; ++i
, mb
++) {
448 if (mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
) {
449 nouveau_vpe_mb_dct_header(dec
, mb
, TRUE
);
450 nouveau_vpe_mb_dct_header(dec
, mb
, FALSE
);
452 nouveau_vpe_mb_mv_header(dec
, mb
, TRUE
);
453 nouveau_vpe_mb_dct_header(dec
, mb
, TRUE
);
455 nouveau_vpe_mb_mv_header(dec
, mb
, FALSE
);
456 nouveau_vpe_mb_dct_header(dec
, mb
, FALSE
);
458 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
459 nouveau_vpe_mb_dct_blocks(dec
, mb
);
461 nouveau_vpe_mb_data_blocks(dec
, mb
);
466 nouveau_decoder_end_frame(struct pipe_video_decoder
*decoder
,
467 struct pipe_video_buffer
*target
,
468 struct pipe_picture_desc
*picture
)
473 nouveau_decoder_flush(struct pipe_video_decoder
*decoder
)
475 struct nouveau_decoder
*dec
= (struct nouveau_decoder
*)decoder
;
477 nouveau_vpe_fini(dec
);
481 nouveau_decoder_destroy(struct pipe_video_decoder
*decoder
)
483 struct nouveau_decoder
*dec
= (struct nouveau_decoder
*)decoder
;
486 nouveau_bo_ref(NULL
, &dec
->data_bo
);
488 nouveau_bo_ref(NULL
, &dec
->cmd_bo
);
490 nouveau_bo_ref(NULL
, &dec
->fence_bo
);
492 nouveau_object_del(&dec
->mpeg
);
495 nouveau_bufctx_del(&dec
->bufctx
);
497 nouveau_pushbuf_del(&dec
->push
);
499 nouveau_client_del(&dec
->client
);
501 nouveau_object_del(&dec
->chan
);
506 static struct pipe_video_decoder
*
507 nouveau_create_decoder(struct pipe_context
*context
,
508 struct nouveau_screen
*screen
,
509 enum pipe_video_profile profile
,
510 enum pipe_video_entrypoint entrypoint
,
511 enum pipe_video_chroma_format chroma_format
,
512 unsigned width
, unsigned height
,
513 unsigned max_references
, bool expect_chunked_decode
)
515 struct nv04_fifo nv04_data
= { .vram
= 0xbeef0201, .gart
= 0xbeef0202 };
516 struct nouveau_object
*mpeg
= NULL
;
517 struct nouveau_decoder
*dec
;
518 struct nouveau_pushbuf
*push
;
520 bool is8274
= screen
->device
->chipset
> 0x80;
522 debug_printf("Acceleration level: %s\n", entrypoint
<= PIPE_VIDEO_ENTRYPOINT_BITSTREAM
? "bit":
523 entrypoint
== PIPE_VIDEO_ENTRYPOINT_IDCT
? "IDCT" : "MC");
525 if (getenv("XVMC_VL"))
527 if (u_reduce_video_profile(profile
) != PIPE_VIDEO_CODEC_MPEG12
)
529 if (screen
->device
->chipset
>= 0x98 && screen
->device
->chipset
!= 0xa0)
532 dec
= CALLOC_STRUCT(nouveau_decoder
);
536 ret
= nouveau_object_new(&screen
->device
->object
, 0,
537 NOUVEAU_FIFO_CHANNEL_CLASS
,
538 &nv04_data
, sizeof(nv04_data
), &dec
->chan
);
541 ret
= nouveau_client_new(screen
->device
, &dec
->client
);
544 ret
= nouveau_pushbuf_new(dec
->client
, dec
->chan
, 2, 4096, 1, &dec
->push
);
547 ret
= nouveau_bufctx_new(dec
->client
, NV31_VIDEO_BIND_COUNT
, &dec
->bufctx
);
552 width
= align(width
, 64);
553 height
= align(height
, 64);
556 ret
= nouveau_object_new(dec
->chan
, 0xbeef8274, NV84_MPEG_CLASS
, NULL
, 0,
559 ret
= nouveau_object_new(dec
->chan
, 0xbeef3174, NV31_MPEG_CLASS
, NULL
, 0,
562 debug_printf("Creation failed: %s (%i)\n", strerror(-ret
), ret
);
567 dec
->base
.context
= context
;
568 dec
->base
.profile
= profile
;
569 dec
->base
.entrypoint
= entrypoint
;
570 dec
->base
.chroma_format
= chroma_format
;
571 dec
->base
.width
= width
;
572 dec
->base
.height
= height
;
573 dec
->base
.max_references
= max_references
;
574 dec
->base
.destroy
= nouveau_decoder_destroy
;
575 dec
->base
.begin_frame
= nouveau_decoder_begin_frame
;
576 dec
->base
.decode_macroblock
= nouveau_decoder_decode_macroblock
;
577 dec
->base
.end_frame
= nouveau_decoder_end_frame
;
578 dec
->base
.flush
= nouveau_decoder_flush
;
579 dec
->screen
= screen
;
581 ret
= nouveau_bo_new(dec
->screen
->device
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
,
582 0, 1024 * 1024, NULL
, &dec
->cmd_bo
);
586 ret
= nouveau_bo_new(dec
->screen
->device
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
,
587 0, width
* height
* 6, NULL
, &dec
->data_bo
);
591 /* we don't need the fence, the kernel sync's for us */
593 ret
= nouveau_bo_new(dec
->screen
->device
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
,
594 0, 4096, NULL
, &dec
->fence_bo
);
597 nouveau_bo_map(dec
->fence_bo
, NOUVEAU_BO_RDWR
, NULL
);
598 dec
->fence_map
= dec
->fence_bo
->map
;
599 dec
->fence_map
[0] = 0;
602 nouveau_pushbuf_bufctx(dec
->push
, dec
->bufctx
);
603 nouveau_pushbuf_space(push
, 32, 4, 0);
605 BEGIN_NV04(push
, SUBC_MPEG(NV01_SUBCHAN_OBJECT
), 1);
606 PUSH_DATA (push
, dec
->mpeg
->handle
);
608 BEGIN_NV04(push
, NV31_MPEG(DMA_CMD
), 1);
609 PUSH_DATA (push
, nv04_data
.gart
);
611 BEGIN_NV04(push
, NV31_MPEG(DMA_DATA
), 1);
612 PUSH_DATA (push
, nv04_data
.gart
);
614 BEGIN_NV04(push
, NV31_MPEG(DMA_IMAGE
), 1);
615 PUSH_DATA (push
, nv04_data
.vram
);
617 BEGIN_NV04(push
, NV31_MPEG(PITCH
), 2);
618 PUSH_DATA (push
, width
| NV31_MPEG_PITCH_UNK
);
619 PUSH_DATA (push
, (height
<< NV31_MPEG_SIZE_H__SHIFT
) | width
);
621 BEGIN_NV04(push
, NV31_MPEG(FORMAT
), 2);
623 switch (entrypoint
) {
624 case PIPE_VIDEO_ENTRYPOINT_BITSTREAM
: PUSH_DATA (push
, 0x100); break;
625 case PIPE_VIDEO_ENTRYPOINT_IDCT
: PUSH_DATA (push
, 1); break;
626 case PIPE_VIDEO_ENTRYPOINT_MC
: PUSH_DATA (push
, 0); break;
631 BEGIN_NV04(push
, NV84_MPEG(DMA_QUERY
), 1);
632 PUSH_DATA (push
, nv04_data
.vram
);
634 BEGIN_NV04(push
, NV84_MPEG(QUERY_OFFSET
), 2);
635 PUSH_DATA (push
, dec
->fence_bo
->offset
);
636 PUSH_DATA (push
, dec
->fence_seq
);
640 ret
= nouveau_vpe_init(dec
);
643 nouveau_vpe_fini(dec
);
647 nouveau_decoder_destroy(&dec
->base
);
651 debug_printf("Using g3dvl renderer\n");
652 return vl_create_decoder(context
, profile
, entrypoint
,
653 chroma_format
, width
, height
,
654 max_references
, expect_chunked_decode
);
657 static struct pipe_sampler_view
**
658 nouveau_video_buffer_sampler_view_planes(struct pipe_video_buffer
*buffer
)
660 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
661 struct pipe_sampler_view sv_templ
;
662 struct pipe_context
*pipe
;
667 pipe
= buf
->base
.context
;
669 for (i
= 0; i
< buf
->num_planes
; ++i
) {
670 if (!buf
->sampler_view_planes
[i
]) {
671 memset(&sv_templ
, 0, sizeof(sv_templ
));
672 u_sampler_view_default_template(&sv_templ
, buf
->resources
[i
], buf
->resources
[i
]->format
);
674 if (util_format_get_nr_components(buf
->resources
[i
]->format
) == 1)
675 sv_templ
.swizzle_r
= sv_templ
.swizzle_g
= sv_templ
.swizzle_b
= sv_templ
.swizzle_a
= PIPE_SWIZZLE_RED
;
677 buf
->sampler_view_planes
[i
] = pipe
->create_sampler_view(pipe
, buf
->resources
[i
], &sv_templ
);
678 if (!buf
->sampler_view_planes
[i
])
683 return buf
->sampler_view_planes
;
686 for (i
= 0; i
< buf
->num_planes
; ++i
)
687 pipe_sampler_view_reference(&buf
->sampler_view_planes
[i
], NULL
);
692 static struct pipe_sampler_view
**
693 nouveau_video_buffer_sampler_view_components(struct pipe_video_buffer
*buffer
)
695 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
696 struct pipe_sampler_view sv_templ
;
697 struct pipe_context
*pipe
;
698 unsigned i
, j
, component
;
702 pipe
= buf
->base
.context
;
704 for (component
= 0, i
= 0; i
< buf
->num_planes
; ++i
) {
705 unsigned nr_components
= util_format_get_nr_components(buf
->resources
[i
]->format
);
707 for (j
= 0; j
< nr_components
; ++j
, ++component
) {
708 assert(component
< VL_NUM_COMPONENTS
);
710 if (!buf
->sampler_view_components
[component
]) {
711 memset(&sv_templ
, 0, sizeof(sv_templ
));
712 u_sampler_view_default_template(&sv_templ
, buf
->resources
[i
], buf
->resources
[i
]->format
);
713 sv_templ
.swizzle_r
= sv_templ
.swizzle_g
= sv_templ
.swizzle_b
= PIPE_SWIZZLE_RED
+ j
;
714 sv_templ
.swizzle_a
= PIPE_SWIZZLE_ONE
;
715 buf
->sampler_view_components
[component
] = pipe
->create_sampler_view(pipe
, buf
->resources
[i
], &sv_templ
);
716 if (!buf
->sampler_view_components
[component
])
722 return buf
->sampler_view_components
;
725 for (i
= 0; i
< 3; ++i
)
726 pipe_sampler_view_reference(&buf
->sampler_view_components
[i
], NULL
);
731 static struct pipe_surface
**
732 nouveau_video_buffer_surfaces(struct pipe_video_buffer
*buffer
)
734 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
735 struct pipe_surface surf_templ
;
736 struct pipe_context
*pipe
;
741 pipe
= buf
->base
.context
;
743 for (i
= 0; i
< buf
->num_planes
; ++i
) {
744 if (!buf
->surfaces
[i
]) {
745 memset(&surf_templ
, 0, sizeof(surf_templ
));
746 surf_templ
.format
= buf
->resources
[i
]->format
;
747 buf
->surfaces
[i
] = pipe
->create_surface(pipe
, buf
->resources
[i
], &surf_templ
);
748 if (!buf
->surfaces
[i
])
753 return buf
->surfaces
;
756 for (i
= 0; i
< buf
->num_planes
; ++i
)
757 pipe_surface_reference(&buf
->surfaces
[i
], NULL
);
763 nouveau_video_buffer_destroy(struct pipe_video_buffer
*buffer
)
765 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
770 for (i
= 0; i
< buf
->num_planes
; ++i
) {
771 pipe_surface_reference(&buf
->surfaces
[i
], NULL
);
772 pipe_sampler_view_reference(&buf
->sampler_view_planes
[i
], NULL
);
773 pipe_sampler_view_reference(&buf
->sampler_view_components
[i
], NULL
);
774 pipe_resource_reference(&buf
->resources
[i
], NULL
);
777 pipe_sampler_view_reference(&buf
->sampler_view_components
[i
], NULL
);
782 static struct pipe_video_buffer
*
783 nouveau_video_buffer_create(struct pipe_context
*pipe
,
784 struct nouveau_screen
*screen
,
785 const struct pipe_video_buffer
*templat
)
787 struct nouveau_video_buffer
*buffer
;
788 struct pipe_resource templ
;
789 unsigned width
, height
;
791 /* Only do a linear surface when a hardware decoder is used
792 * hardware decoder is only supported on some chipsets
793 * and it only supports the NV12 format
795 if (templat
->buffer_format
!= PIPE_FORMAT_NV12
|| getenv("XVMC_VL") ||
796 (screen
->device
->chipset
>= 0x98 && screen
->device
->chipset
!= 0xa0))
797 return vl_video_buffer_create(pipe
, templat
);
799 assert(templat
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
800 width
= align(templat
->width
, 64);
801 height
= align(templat
->height
, 64);
803 buffer
= CALLOC_STRUCT(nouveau_video_buffer
);
807 buffer
->base
.context
= pipe
;
808 buffer
->base
.destroy
= nouveau_video_buffer_destroy
;
809 buffer
->base
.get_sampler_view_planes
= nouveau_video_buffer_sampler_view_planes
;
810 buffer
->base
.get_sampler_view_components
= nouveau_video_buffer_sampler_view_components
;
811 buffer
->base
.get_surfaces
= nouveau_video_buffer_surfaces
;
812 buffer
->base
.chroma_format
= templat
->chroma_format
;
813 buffer
->base
.width
= width
;
814 buffer
->base
.height
= height
;
815 buffer
->num_planes
= 2;
817 memset(&templ
, 0, sizeof(templ
));
818 templ
.target
= PIPE_TEXTURE_2D
;
819 templ
.format
= PIPE_FORMAT_R8_UNORM
;
820 templ
.width0
= width
;
821 templ
.height0
= height
;
823 templ
.array_size
= 1;
824 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
825 templ
.usage
= PIPE_USAGE_STATIC
;
826 templ
.flags
= NOUVEAU_RESOURCE_FLAG_LINEAR
;
828 buffer
->resources
[0] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
829 if (!buffer
->resources
[0])
833 templ
.format
= PIPE_FORMAT_R8G8_UNORM
;
834 buffer
->resources
[1] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
835 if (!buffer
->resources
[1])
837 return &buffer
->base
;
840 nouveau_video_buffer_destroy(&buffer
->base
);
845 nouveau_screen_get_video_param(struct pipe_screen
*pscreen
,
846 enum pipe_video_profile profile
,
847 enum pipe_video_cap param
)
850 case PIPE_VIDEO_CAP_SUPPORTED
:
851 return vl_profile_supported(pscreen
, profile
);
852 case PIPE_VIDEO_CAP_NPOT_TEXTURES
:
854 case PIPE_VIDEO_CAP_MAX_WIDTH
:
855 case PIPE_VIDEO_CAP_MAX_HEIGHT
:
856 return vl_video_buffer_max_size(pscreen
);
857 case PIPE_VIDEO_CAP_PREFERED_FORMAT
:
858 return PIPE_FORMAT_NV12
;
859 case PIPE_VIDEO_CAP_PREFERS_INTERLACED
:
861 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED
:
863 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE
:
866 debug_printf("unknown video param: %d\n", param
);
872 nouveau_screen_init_vdec(struct nouveau_screen
*screen
)
874 screen
->base
.get_video_param
= nouveau_screen_get_video_param
;
875 screen
->base
.is_video_format_supported
= vl_video_buffer_is_format_supported
;
878 static struct pipe_video_decoder
*
879 nouveau_context_create_decoder(struct pipe_context
*context
,
880 enum pipe_video_profile profile
,
881 enum pipe_video_entrypoint entrypoint
,
882 enum pipe_video_chroma_format chroma_format
,
883 unsigned width
, unsigned height
,
884 unsigned max_references
, bool expect_chunked_decode
)
886 struct nouveau_screen
*screen
= nouveau_context(context
)->screen
;
887 return nouveau_create_decoder(context
, screen
, profile
, entrypoint
,
888 chroma_format
, width
, height
,
889 max_references
, expect_chunked_decode
);
892 static struct pipe_video_buffer
*
893 nouveau_context_video_buffer_create(struct pipe_context
*pipe
,
894 const struct pipe_video_buffer
*templat
)
896 struct nouveau_screen
*screen
= nouveau_context(pipe
)->screen
;
897 return nouveau_video_buffer_create(pipe
, screen
, templat
);
901 nouveau_context_init_vdec(struct nouveau_context
*nv
)
903 nv
->pipe
.create_video_decoder
= nouveau_context_create_decoder
;
904 nv
->pipe
.create_video_buffer
= nouveau_context_video_buffer_create
;