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 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.
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_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) {
112 for (i
= 0; i
< 64; ++i
) {
113 if (!db
[i
]) continue;
114 dec
->data
[dec
->data_pos
++] = (db
[i
] << 16) | (i
* 2);
118 dec
->data
[dec
->data_pos
- 1] |= 1;
120 dec
->data
[dec
->data_pos
++] = 1;
122 } else if (mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
) {
123 dec
->data
[dec
->data_pos
++] = 1;
129 nouveau_vpe_mb_data_blocks(struct nouveau_decoder
*dec
, const struct pipe_mpeg12_macroblock
*mb
)
132 unsigned cbp
= mb
->coded_block_pattern
;
133 short *db
= mb
->blocks
;
134 for (cbb
= 0x20; cbb
> 0; cbb
>>= 1) {
136 memcpy(&dec
->data
[dec
->data_pos
], db
, 128);
139 } else if (mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
) {
140 memset(&dec
->data
[dec
->data_pos
], 0, 128);
147 nouveau_vpe_mb_dct_header(struct nouveau_decoder
*dec
,
148 const struct pipe_mpeg12_macroblock
*mb
,
151 unsigned base_dct
, cbp
;
152 bool intra
= mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
;
153 unsigned x
= mb
->x
* 16;
154 unsigned y
= luma
? mb
->y
* 16 : mb
->y
* 8;
156 /* Setup the base dct header */
157 base_dct
= dec
->current
<< NV17_MPEG_CMD_CHROMA_MB_HEADER_SURFACE__SHIFT
;
158 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_RUN_SINGLE
;
161 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_X_COORD_EVEN
;
165 cbp
= mb
->coded_block_pattern
;
167 if (dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FRAME
) {
168 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_TYPE_FRAME
;
169 if (luma
&& mb
->macroblock_modes
.bits
.dct_type
== PIPE_MPEG12_DCT_TYPE_FIELD
)
170 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_FRAME_DCT_TYPE_FIELD
;
172 if (dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_BOTTOM
)
173 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_FIELD_BOTTOM
;
179 base_dct
|= NV17_MPEG_CMD_LUMA_MB_HEADER_OP_LUMA_MB_HEADER
;
180 base_dct
|= (cbp
>> 2) << NV17_MPEG_CMD_LUMA_MB_HEADER_CBP__SHIFT
;
182 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_OP_CHROMA_MB_HEADER
;
183 base_dct
|= (cbp
& 3) << NV17_MPEG_CMD_CHROMA_MB_HEADER_CBP__SHIFT
;
185 nouveau_vpe_write(dec
, base_dct
);
186 nouveau_vpe_write(dec
, NV17_MPEG_CMD_MB_COORDS_OP_MB_COORDS
|
187 x
| (y
<< NV17_MPEG_CMD_MB_COORDS_Y__SHIFT
));
190 static inline unsigned int
191 nouveau_vpe_mb_mv_flags(bool luma
, int mv_h
, int mv_v
, bool forward
, bool first
, bool vert
)
193 unsigned mc_header
= 0;
195 mc_header
|= NV17_MPEG_CMD_LUMA_MV_HEADER_OP_LUMA_MV_HEADER
;
197 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_OP_CHROMA_MV_HEADER
;
199 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_X_HALF
;
201 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_Y_HALF
;
203 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_DIRECTION_BACKWARD
;
205 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_IDX
;
207 mc_header
|= NV17_MPEG_CMD_LUMA_MV_HEADER_FIELD_BOTTOM
;
211 static unsigned pos(int pos
, int mov
, int max
) {
220 /* because we want -1 / 2 = -1 */
221 static int div_down(int val
, int mult
) {
226 static int div_up(int val
, int mult
) {
232 nouveau_vpe_mb_mv(struct nouveau_decoder
*dec
, unsigned mc_header
,
233 bool luma
, bool frame
, bool forward
, bool vert
,
234 int x
, int y
, const short motions
[2],
235 unsigned surface
, bool first
)
238 int mv_horizontal
= motions
[0];
239 int mv_vertical
= motions
[1];
240 int mv2
= mc_header
& NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2
;
241 unsigned width
= dec
->base
.width
;
242 unsigned height
= dec
->base
.height
;
244 mv_vertical
= div_down(mv_vertical
, 2);
245 assert(frame
); // Untested for non-frames
249 mc_header
|= surface
<< NV17_MPEG_CMD_CHROMA_MV_HEADER_SURFACE__SHIFT
;
251 mv_vertical
= div_up(mv_vertical
, 2);
252 mv_horizontal
= div_up(mv_horizontal
, 2);
255 mc_header
|= nouveau_vpe_mb_mv_flags(luma
, mv_horizontal
, mv_vertical
, forward
, first
, vert
);
256 nouveau_vpe_write(dec
, mc_header
);
258 mc_vector
= NV17_MPEG_CMD_MV_COORDS_OP_MV_COORDS
;
260 mc_vector
|= pos(x
, div_down(mv_horizontal
, 2), width
);
262 mc_vector
|= pos(x
, mv_horizontal
& ~1, width
);
264 mc_vector
|= pos(y
, div_down(mv_vertical
, 2), height
) << NV17_MPEG_CMD_MV_COORDS_Y__SHIFT
;
266 mc_vector
|= pos(y
, mv_vertical
& ~1, height
) << NV17_MPEG_CMD_MV_COORDS_Y__SHIFT
;
267 nouveau_vpe_write(dec
, mc_vector
);
271 nouveau_vpe_mb_mv_header(struct nouveau_decoder
*dec
,
272 const struct pipe_mpeg12_macroblock
*mb
,
275 bool frame
= dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FRAME
;
277 bool forward
, backward
;
278 int y
, y2
, x
= mb
->x
* 16;
280 y
= mb
->y
* (frame
? 16 : 32);
282 y
= mb
->y
* (frame
? 8 : 16);
286 y2
= y
+ (luma
? 16 : 8);
288 forward
= mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_MOTION_FORWARD
;
289 backward
= mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD
;
290 assert(!forward
|| dec
->past
< 8);
291 assert(!backward
|| dec
->future
< 8);
293 switch (mb
->macroblock_modes
.bits
.frame_motion_type
) {
294 case PIPE_MPEG12_MO_TYPE_FRAME
: goto mv1
;
295 case PIPE_MPEG12_MO_TYPE_FIELD
: goto mv2
;
296 case PIPE_MPEG12_MO_TYPE_DUAL_PRIME
: {
297 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2
;
299 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, true, false,
300 x
, y
, mb
->PMV
[0][0], dec
->past
, true);
301 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, true, true,
302 x
, y2
, mb
->PMV
[0][0], dec
->past
, false);
304 if (backward
&& forward
) {
305 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
, true,
306 x
, y
, mb
->PMV
[1][0], dec
->future
, true);
307 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
, false,
308 x
, y2
, mb
->PMV
[1][1], dec
->future
, false);
309 } else assert(!backward
);
315 switch (mb
->macroblock_modes
.bits
.field_motion_type
) {
316 case PIPE_MPEG12_MO_TYPE_FIELD
: goto mv1
;
317 case PIPE_MPEG12_MO_TYPE_16x8
: goto mv2
;
318 case PIPE_MPEG12_MO_TYPE_DUAL_PRIME
: {
319 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB
;
321 base
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_TYPE_FRAME
;
323 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, true,
324 dec
->picture_structure
!= PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_TOP
,
325 x
, y
, mb
->PMV
[0][0], dec
->past
, true);
326 if (backward
&& forward
)
327 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, false,
328 dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_TOP
,
329 x
, y
, mb
->PMV
[0][1], dec
->future
, true);
330 else assert(!backward
);
339 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB
;
341 base
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_TYPE_FRAME
;
344 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, true, false,
345 x
, y
, mb
->PMV
[0][0], dec
->past
, true);
347 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
, false,
348 x
, y
, mb
->PMV
[0][1], dec
->future
, true);
352 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2
;
354 base
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB
;
356 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, true,
357 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_FIRST_FORWARD
,
358 x
, y
, mb
->PMV
[0][0], dec
->past
, true);
359 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, true,
360 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_SECOND_FORWARD
,
361 x
, y2
, mb
->PMV
[1][0], dec
->past
, false);
364 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
,
365 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_FIRST_BACKWARD
,
366 x
, y
, mb
->PMV
[0][1], dec
->future
, true);
367 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
,
368 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_SECOND_BACKWARD
,
369 x
, y2
, mb
->PMV
[1][1], dec
->future
, false);
374 nouveau_decoder_surface_index(struct nouveau_decoder
*dec
,
375 struct pipe_video_buffer
*buffer
)
377 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
378 struct nouveau_pushbuf
*push
= dec
->push
;
379 struct nouveau_bo
*bo_y
= nv04_resource(buf
->resources
[0])->bo
;
380 struct nouveau_bo
*bo_c
= nv04_resource(buf
->resources
[1])->bo
;
384 for (i
= 0; i
< dec
->num_surfaces
; ++i
) {
385 if (dec
->surfaces
[i
] == buf
)
389 dec
->surfaces
[i
] = buf
;
392 nouveau_bufctx_reset(dec
->bufctx
, NV31_VIDEO_BIND_IMG(i
));
394 #define BCTX_ARGS dec->bufctx, NV31_VIDEO_BIND_IMG(i), NOUVEAU_BO_RDWR
395 BEGIN_NV04(push
, NV31_MPEG(IMAGE_Y_OFFSET(i
)), 2);
396 PUSH_MTHDl(push
, NV31_MPEG(IMAGE_Y_OFFSET(i
)), bo_y
, 0, BCTX_ARGS
);
397 PUSH_MTHDl(push
, NV31_MPEG(IMAGE_C_OFFSET(i
)), bo_c
, 0, BCTX_ARGS
);
404 nouveau_decoder_begin_frame(struct pipe_video_codec
*decoder
,
405 struct pipe_video_buffer
*target
,
406 struct pipe_picture_desc
*picture
)
411 nouveau_decoder_decode_macroblock(struct pipe_video_codec
*decoder
,
412 struct pipe_video_buffer
*target
,
413 struct pipe_picture_desc
*picture
,
414 const struct pipe_macroblock
*pipe_mb
,
415 unsigned num_macroblocks
)
417 struct nouveau_decoder
*dec
= (struct nouveau_decoder
*)decoder
;
418 struct pipe_mpeg12_picture_desc
*desc
= (struct pipe_mpeg12_picture_desc
*)picture
;
419 const struct pipe_mpeg12_macroblock
*mb
;
421 assert(target
->width
== decoder
->width
);
422 assert(target
->height
== decoder
->height
);
424 dec
->current
= nouveau_decoder_surface_index(dec
, target
);
425 assert(dec
->current
< 8);
426 dec
->picture_structure
= desc
->picture_structure
;
428 dec
->future
= nouveau_decoder_surface_index(dec
, desc
->ref
[1]);
430 dec
->past
= nouveau_decoder_surface_index(dec
, desc
->ref
[0]);
432 if (nouveau_vpe_init(dec
)) return;
434 /* initialize scan order */
435 nouveau_vpe_write(dec
, 0x720000c0);
436 nouveau_vpe_write(dec
, dec
->data_pos
);
438 mb
= (const struct pipe_mpeg12_macroblock
*)pipe_mb
;
439 for (i
= 0; i
< num_macroblocks
; ++i
, mb
++) {
440 if (mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
) {
441 nouveau_vpe_mb_dct_header(dec
, mb
, true);
442 nouveau_vpe_mb_dct_header(dec
, mb
, false);
444 nouveau_vpe_mb_mv_header(dec
, mb
, true);
445 nouveau_vpe_mb_dct_header(dec
, mb
, true);
447 nouveau_vpe_mb_mv_header(dec
, mb
, false);
448 nouveau_vpe_mb_dct_header(dec
, mb
, false);
450 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
451 nouveau_vpe_mb_dct_blocks(dec
, mb
);
453 nouveau_vpe_mb_data_blocks(dec
, mb
);
458 nouveau_decoder_end_frame(struct pipe_video_codec
*decoder
,
459 struct pipe_video_buffer
*target
,
460 struct pipe_picture_desc
*picture
)
465 nouveau_decoder_flush(struct pipe_video_codec
*decoder
)
467 struct nouveau_decoder
*dec
= (struct nouveau_decoder
*)decoder
;
469 nouveau_vpe_fini(dec
);
473 nouveau_decoder_destroy(struct pipe_video_codec
*decoder
)
475 struct nouveau_decoder
*dec
= (struct nouveau_decoder
*)decoder
;
478 nouveau_bo_ref(NULL
, &dec
->data_bo
);
480 nouveau_bo_ref(NULL
, &dec
->cmd_bo
);
482 nouveau_bo_ref(NULL
, &dec
->fence_bo
);
484 nouveau_object_del(&dec
->mpeg
);
487 nouveau_bufctx_del(&dec
->bufctx
);
489 nouveau_pushbuf_del(&dec
->push
);
491 nouveau_client_del(&dec
->client
);
493 nouveau_object_del(&dec
->chan
);
498 static struct pipe_video_codec
*
499 nouveau_create_decoder(struct pipe_context
*context
,
500 const struct pipe_video_codec
*templ
,
501 struct nouveau_screen
*screen
)
503 struct nv04_fifo nv04_data
= { .vram
= 0xbeef0201, .gart
= 0xbeef0202 };
504 unsigned width
= templ
->width
, height
= templ
->height
;
505 struct nouveau_object
*mpeg
= NULL
;
506 struct nouveau_decoder
*dec
;
507 struct nouveau_pushbuf
*push
;
509 bool is8274
= screen
->device
->chipset
> 0x80;
511 debug_printf("Acceleration level: %s\n", templ
->entrypoint
<= PIPE_VIDEO_ENTRYPOINT_BITSTREAM
? "bit":
512 templ
->entrypoint
== PIPE_VIDEO_ENTRYPOINT_IDCT
? "IDCT" : "MC");
514 if (getenv("XVMC_VL"))
516 if (u_reduce_video_profile(templ
->profile
) != PIPE_VIDEO_FORMAT_MPEG12
)
518 if (screen
->device
->chipset
>= 0x98 && screen
->device
->chipset
!= 0xa0)
520 if (screen
->device
->chipset
< 0x40)
523 dec
= CALLOC_STRUCT(nouveau_decoder
);
527 ret
= nouveau_object_new(&screen
->device
->object
, 0,
528 NOUVEAU_FIFO_CHANNEL_CLASS
,
529 &nv04_data
, sizeof(nv04_data
), &dec
->chan
);
532 ret
= nouveau_client_new(screen
->device
, &dec
->client
);
535 ret
= nouveau_pushbuf_new(dec
->client
, dec
->chan
, 2, 4096, 1, &dec
->push
);
538 ret
= nouveau_bufctx_new(dec
->client
, NV31_VIDEO_BIND_COUNT
, &dec
->bufctx
);
543 width
= align(width
, 64);
544 height
= align(height
, 64);
547 ret
= nouveau_object_new(dec
->chan
, 0xbeef8274, NV84_MPEG_CLASS
, NULL
, 0,
550 ret
= nouveau_object_new(dec
->chan
, 0xbeef3174, NV31_MPEG_CLASS
, NULL
, 0,
553 debug_printf("Creation failed: %s (%i)\n", strerror(-ret
), ret
);
559 dec
->base
.context
= context
;
560 dec
->base
.width
= width
;
561 dec
->base
.height
= height
;
562 dec
->base
.destroy
= nouveau_decoder_destroy
;
563 dec
->base
.begin_frame
= nouveau_decoder_begin_frame
;
564 dec
->base
.decode_macroblock
= nouveau_decoder_decode_macroblock
;
565 dec
->base
.end_frame
= nouveau_decoder_end_frame
;
566 dec
->base
.flush
= nouveau_decoder_flush
;
567 dec
->screen
= screen
;
569 ret
= nouveau_bo_new(dec
->screen
->device
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
,
570 0, 1024 * 1024, NULL
, &dec
->cmd_bo
);
574 ret
= nouveau_bo_new(dec
->screen
->device
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
,
575 0, width
* height
* 6, NULL
, &dec
->data_bo
);
579 /* we don't need the fence, the kernel sync's for us */
581 ret
= nouveau_bo_new(dec
->screen
->device
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
,
582 0, 4096, NULL
, &dec
->fence_bo
);
585 nouveau_bo_map(dec
->fence_bo
, NOUVEAU_BO_RDWR
, NULL
);
586 dec
->fence_map
= dec
->fence_bo
->map
;
587 dec
->fence_map
[0] = 0;
590 nouveau_pushbuf_bufctx(dec
->push
, dec
->bufctx
);
591 nouveau_pushbuf_space(push
, 32, 4, 0);
593 BEGIN_NV04(push
, SUBC_MPEG(NV01_SUBCHAN_OBJECT
), 1);
594 PUSH_DATA (push
, dec
->mpeg
->handle
);
596 BEGIN_NV04(push
, NV31_MPEG(DMA_CMD
), 1);
597 PUSH_DATA (push
, nv04_data
.gart
);
599 BEGIN_NV04(push
, NV31_MPEG(DMA_DATA
), 1);
600 PUSH_DATA (push
, nv04_data
.gart
);
602 BEGIN_NV04(push
, NV31_MPEG(DMA_IMAGE
), 1);
603 PUSH_DATA (push
, nv04_data
.vram
);
605 BEGIN_NV04(push
, NV31_MPEG(PITCH
), 2);
606 PUSH_DATA (push
, width
| NV31_MPEG_PITCH_UNK
);
607 PUSH_DATA (push
, (height
<< NV31_MPEG_SIZE_H__SHIFT
) | width
);
609 BEGIN_NV04(push
, NV31_MPEG(FORMAT
), 2);
611 switch (templ
->entrypoint
) {
612 case PIPE_VIDEO_ENTRYPOINT_IDCT
: PUSH_DATA (push
, 1); break;
613 case PIPE_VIDEO_ENTRYPOINT_MC
: PUSH_DATA (push
, 0); break;
618 BEGIN_NV04(push
, NV84_MPEG(DMA_QUERY
), 1);
619 PUSH_DATA (push
, nv04_data
.vram
);
621 BEGIN_NV04(push
, NV84_MPEG(QUERY_OFFSET
), 2);
622 PUSH_DATA (push
, dec
->fence_bo
->offset
);
623 PUSH_DATA (push
, dec
->fence_seq
);
627 ret
= nouveau_vpe_init(dec
);
630 nouveau_vpe_fini(dec
);
634 nouveau_decoder_destroy(&dec
->base
);
638 debug_printf("Using g3dvl renderer\n");
639 return vl_create_decoder(context
, templ
);
642 static struct pipe_sampler_view
**
643 nouveau_video_buffer_sampler_view_planes(struct pipe_video_buffer
*buffer
)
645 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
646 struct pipe_sampler_view sv_templ
;
647 struct pipe_context
*pipe
;
652 pipe
= buf
->base
.context
;
654 for (i
= 0; i
< buf
->num_planes
; ++i
) {
655 if (!buf
->sampler_view_planes
[i
]) {
656 memset(&sv_templ
, 0, sizeof(sv_templ
));
657 u_sampler_view_default_template(&sv_templ
, buf
->resources
[i
], buf
->resources
[i
]->format
);
659 if (util_format_get_nr_components(buf
->resources
[i
]->format
) == 1)
660 sv_templ
.swizzle_r
= sv_templ
.swizzle_g
= sv_templ
.swizzle_b
= sv_templ
.swizzle_a
= PIPE_SWIZZLE_RED
;
662 buf
->sampler_view_planes
[i
] = pipe
->create_sampler_view(pipe
, buf
->resources
[i
], &sv_templ
);
663 if (!buf
->sampler_view_planes
[i
])
668 return buf
->sampler_view_planes
;
671 for (i
= 0; i
< buf
->num_planes
; ++i
)
672 pipe_sampler_view_reference(&buf
->sampler_view_planes
[i
], NULL
);
677 static struct pipe_sampler_view
**
678 nouveau_video_buffer_sampler_view_components(struct pipe_video_buffer
*buffer
)
680 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
681 struct pipe_sampler_view sv_templ
;
682 struct pipe_context
*pipe
;
683 unsigned i
, j
, component
;
687 pipe
= buf
->base
.context
;
689 for (component
= 0, i
= 0; i
< buf
->num_planes
; ++i
) {
690 unsigned nr_components
= util_format_get_nr_components(buf
->resources
[i
]->format
);
692 for (j
= 0; j
< nr_components
; ++j
, ++component
) {
693 assert(component
< VL_NUM_COMPONENTS
);
695 if (!buf
->sampler_view_components
[component
]) {
696 memset(&sv_templ
, 0, sizeof(sv_templ
));
697 u_sampler_view_default_template(&sv_templ
, buf
->resources
[i
], buf
->resources
[i
]->format
);
698 sv_templ
.swizzle_r
= sv_templ
.swizzle_g
= sv_templ
.swizzle_b
= PIPE_SWIZZLE_RED
+ j
;
699 sv_templ
.swizzle_a
= PIPE_SWIZZLE_ONE
;
700 buf
->sampler_view_components
[component
] = pipe
->create_sampler_view(pipe
, buf
->resources
[i
], &sv_templ
);
701 if (!buf
->sampler_view_components
[component
])
707 return buf
->sampler_view_components
;
710 for (i
= 0; i
< 3; ++i
)
711 pipe_sampler_view_reference(&buf
->sampler_view_components
[i
], NULL
);
716 static struct pipe_surface
**
717 nouveau_video_buffer_surfaces(struct pipe_video_buffer
*buffer
)
719 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
720 struct pipe_surface surf_templ
;
721 struct pipe_context
*pipe
;
726 pipe
= buf
->base
.context
;
728 for (i
= 0; i
< buf
->num_planes
; ++i
) {
729 if (!buf
->surfaces
[i
]) {
730 memset(&surf_templ
, 0, sizeof(surf_templ
));
731 surf_templ
.format
= buf
->resources
[i
]->format
;
732 buf
->surfaces
[i
] = pipe
->create_surface(pipe
, buf
->resources
[i
], &surf_templ
);
733 if (!buf
->surfaces
[i
])
738 return buf
->surfaces
;
741 for (i
= 0; i
< buf
->num_planes
; ++i
)
742 pipe_surface_reference(&buf
->surfaces
[i
], NULL
);
748 nouveau_video_buffer_destroy(struct pipe_video_buffer
*buffer
)
750 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
755 for (i
= 0; i
< buf
->num_planes
; ++i
) {
756 pipe_surface_reference(&buf
->surfaces
[i
], NULL
);
757 pipe_sampler_view_reference(&buf
->sampler_view_planes
[i
], NULL
);
758 pipe_sampler_view_reference(&buf
->sampler_view_components
[i
], NULL
);
759 pipe_resource_reference(&buf
->resources
[i
], NULL
);
762 pipe_sampler_view_reference(&buf
->sampler_view_components
[i
], NULL
);
767 static struct pipe_video_buffer
*
768 nouveau_video_buffer_create(struct pipe_context
*pipe
,
769 struct nouveau_screen
*screen
,
770 const struct pipe_video_buffer
*templat
)
772 struct nouveau_video_buffer
*buffer
;
773 struct pipe_resource templ
;
774 unsigned width
, height
;
776 /* Only do a linear surface when a hardware decoder is used
777 * hardware decoder is only supported on some chipsets
778 * and it only supports the NV12 format
780 if (templat
->buffer_format
!= PIPE_FORMAT_NV12
|| getenv("XVMC_VL") ||
781 (screen
->device
->chipset
>= 0x98 && screen
->device
->chipset
!= 0xa0) ||
782 screen
->device
->chipset
< 0x40)
783 return vl_video_buffer_create(pipe
, templat
);
785 assert(templat
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
786 width
= align(templat
->width
, 64);
787 height
= align(templat
->height
, 64);
789 buffer
= CALLOC_STRUCT(nouveau_video_buffer
);
793 buffer
->base
.context
= pipe
;
794 buffer
->base
.destroy
= nouveau_video_buffer_destroy
;
795 buffer
->base
.get_sampler_view_planes
= nouveau_video_buffer_sampler_view_planes
;
796 buffer
->base
.get_sampler_view_components
= nouveau_video_buffer_sampler_view_components
;
797 buffer
->base
.get_surfaces
= nouveau_video_buffer_surfaces
;
798 buffer
->base
.chroma_format
= templat
->chroma_format
;
799 buffer
->base
.buffer_format
= templat
->buffer_format
;
800 buffer
->base
.width
= width
;
801 buffer
->base
.height
= height
;
802 buffer
->num_planes
= 2;
804 memset(&templ
, 0, sizeof(templ
));
805 templ
.target
= PIPE_TEXTURE_2D
;
806 templ
.format
= PIPE_FORMAT_R8_UNORM
;
807 templ
.width0
= width
;
808 templ
.height0
= height
;
810 templ
.array_size
= 1;
811 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
812 templ
.usage
= PIPE_USAGE_DEFAULT
;
813 templ
.flags
= NOUVEAU_RESOURCE_FLAG_LINEAR
;
815 buffer
->resources
[0] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
816 if (!buffer
->resources
[0])
820 templ
.format
= PIPE_FORMAT_R8G8_UNORM
;
821 buffer
->resources
[1] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
822 if (!buffer
->resources
[1])
824 return &buffer
->base
;
827 nouveau_video_buffer_destroy(&buffer
->base
);
832 nouveau_screen_get_video_param(struct pipe_screen
*pscreen
,
833 enum pipe_video_profile profile
,
834 enum pipe_video_entrypoint entrypoint
,
835 enum pipe_video_cap param
)
838 case PIPE_VIDEO_CAP_SUPPORTED
:
839 return entrypoint
>= PIPE_VIDEO_ENTRYPOINT_IDCT
&&
840 u_reduce_video_profile(profile
) == PIPE_VIDEO_FORMAT_MPEG12
;
841 case PIPE_VIDEO_CAP_NPOT_TEXTURES
:
843 case PIPE_VIDEO_CAP_MAX_WIDTH
:
844 case PIPE_VIDEO_CAP_MAX_HEIGHT
:
845 return vl_video_buffer_max_size(pscreen
);
846 case PIPE_VIDEO_CAP_PREFERED_FORMAT
:
847 return PIPE_FORMAT_NV12
;
848 case PIPE_VIDEO_CAP_PREFERS_INTERLACED
:
850 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED
:
852 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE
:
854 case PIPE_VIDEO_CAP_MAX_LEVEL
:
855 return vl_level_supported(pscreen
, profile
);
857 debug_printf("unknown video param: %d\n", param
);
863 nouveau_screen_init_vdec(struct nouveau_screen
*screen
)
865 screen
->base
.get_video_param
= nouveau_screen_get_video_param
;
866 screen
->base
.is_video_format_supported
= vl_video_buffer_is_format_supported
;
869 static struct pipe_video_codec
*
870 nouveau_context_create_decoder(struct pipe_context
*context
,
871 const struct pipe_video_codec
*templ
)
873 struct nouveau_screen
*screen
= nouveau_context(context
)->screen
;
874 return nouveau_create_decoder(context
, templ
, screen
);
877 static struct pipe_video_buffer
*
878 nouveau_context_video_buffer_create(struct pipe_context
*pipe
,
879 const struct pipe_video_buffer
*templat
)
881 struct nouveau_screen
*screen
= nouveau_context(pipe
)->screen
;
882 return nouveau_video_buffer_create(pipe
, screen
, templat
);
886 nouveau_context_init_vdec(struct nouveau_context
*nv
)
888 nv
->pipe
.create_video_codec
= nouveau_context_create_decoder
;
889 nv
->pipe
.create_video_buffer
= nouveau_context_video_buffer_create
;