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_bo.h"
31 #include "nouveau/nouveau_buffer.h"
32 #include "util/u_video.h"
33 #include "util/u_format.h"
34 #include "util/u_sampler.h"
35 #include "nouveau/nouveau_device.h"
36 #include "nouveau_winsys.h"
39 nouveau_vpe_init(struct nouveau_decoder
*dec
) {
43 ret
= nouveau_bo_map(dec
->cmd_bo
, NOUVEAU_BO_RDWR
);
45 debug_printf("Mapping cmd bo: %s\n", strerror(-ret
));
48 ret
= nouveau_bo_map(dec
->data_bo
, NOUVEAU_BO_RDWR
);
50 nouveau_bo_unmap(dec
->cmd_bo
);
51 debug_printf("Mapping data bo: %s\n", strerror(-ret
));
54 dec
->cmds
= dec
->cmd_bo
->map
;
55 dec
->data
= dec
->data_bo
->map
;
60 nouveau_vpe_synch(struct nouveau_decoder
*dec
) {
61 struct nouveau_channel
*chan
= dec
->screen
->channel
;
64 BEGIN_RING(chan
, dec
->mpeg
, NV84_MPEG_QUERY_COUNTER
, 1);
65 OUT_RING(chan
, ++dec
->fence_seq
);
67 while (dec
->fence_map
[0] != dec
->fence_seq
)
75 nouveau_vpe_fini(struct nouveau_decoder
*dec
) {
76 struct nouveau_channel
*chan
= dec
->screen
->channel
;
80 nouveau_bo_unmap(dec
->data_bo
);
81 nouveau_bo_unmap(dec
->cmd_bo
);
83 MARK_RING(chan
, 8, 2);
84 BEGIN_RING(chan
, dec
->mpeg
, NV31_MPEG_CMD_OFFSET
, 2);
85 OUT_RELOCl(chan
, dec
->cmd_bo
, 0, NOUVEAU_BO_RD
|NOUVEAU_BO_GART
);
86 OUT_RING(chan
, dec
->ofs
* 4);
88 BEGIN_RING(chan
, dec
->mpeg
, NV31_MPEG_DATA_OFFSET
, 2);
89 OUT_RELOCl(chan
, dec
->data_bo
, 0, NOUVEAU_BO_RD
|NOUVEAU_BO_GART
);
90 OUT_RING(chan
, dec
->data_pos
* 4);
92 BEGIN_RING(chan
, dec
->mpeg
, NV31_MPEG_EXEC
, 1);
95 nouveau_vpe_synch(dec
);
96 dec
->ofs
= dec
->data_pos
= dec
->num_surfaces
= 0;
97 dec
->cmds
= dec
->data
= NULL
;
98 dec
->current
= dec
->future
= dec
->past
= 8;
102 nouveau_vpe_mb_dct_blocks(struct nouveau_decoder
*dec
, const struct pipe_mpeg12_macroblock
*mb
)
105 unsigned cbp
= mb
->coded_block_pattern
;
106 short *db
= mb
->blocks
;
107 for (cbb
= 0x20; cbb
> 0; cbb
>>= 1) {
109 static const int lookup
[64] = {
110 0, 1, 8,16, 9, 2, 3,10,
111 17,24,32,25,18,11, 4, 5,
112 12,19,26,33,40,48,41,34,
113 27,20,13, 6, 7,14,21,28,
114 35,42,49,56,57,50,43,36,
115 29,22,15,23,30,37,44,51,
116 58,59,52,45,38,31,39,46,
117 53,60,61,54,47,55,62,63
119 int i
, j
= 0, found
= 0;
120 for (i
= 0; i
< 64; ++i
) {
121 if (!db
[lookup
[i
]]) { j
+= 2; continue; }
122 dec
->data
[dec
->data_pos
++] = (db
[lookup
[i
]] << 16) | j
;
127 dec
->data
[dec
->data_pos
- 1] |= 1;
129 dec
->data
[dec
->data_pos
++] = 1;
131 } else if (mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
) {
132 dec
->data
[dec
->data_pos
++] = 1;
138 nouveau_vpe_mb_data_blocks(struct nouveau_decoder
*dec
, const struct pipe_mpeg12_macroblock
*mb
)
141 unsigned cbp
= mb
->coded_block_pattern
;
142 short *db
= mb
->blocks
;
143 for (cbb
= 0x20; cbb
> 0; cbb
>>= 1) {
145 memcpy(&dec
->data
[dec
->data_pos
], db
, 128);
148 } else if (mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
) {
149 memset(&dec
->data
[dec
->data_pos
], 0, 128);
156 nouveau_vpe_mb_dct_header(struct nouveau_decoder
*dec
,
157 const struct pipe_mpeg12_macroblock
*mb
,
160 unsigned base_dct
, cbp
;
161 bool intra
= mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
;
162 unsigned x
= mb
->x
* 16;
163 unsigned y
= luma
? mb
->y
* 16 : mb
->y
* 8;
165 /* Setup the base dct header */
166 base_dct
= dec
->current
<< NV17_MPEG_CMD_CHROMA_MB_HEADER_SURFACE__SHIFT
;
167 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_RUN_SINGLE
;
170 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_X_COORD_EVEN
;
174 cbp
= mb
->coded_block_pattern
;
176 if (dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FRAME
) {
177 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_TYPE_FRAME
;
178 if (luma
&& mb
->macroblock_modes
.bits
.dct_type
== PIPE_MPEG12_DCT_TYPE_FIELD
)
179 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_FRAME_DCT_TYPE_FIELD
;
181 if (dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_BOTTOM
)
182 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_FIELD_BOTTOM
;
188 base_dct
|= NV17_MPEG_CMD_LUMA_MB_HEADER_OP_LUMA_MB_HEADER
;
189 base_dct
|= (cbp
>> 2) << NV17_MPEG_CMD_LUMA_MB_HEADER_CBP__SHIFT
;
191 base_dct
|= NV17_MPEG_CMD_CHROMA_MB_HEADER_OP_CHROMA_MB_HEADER
;
192 base_dct
|= (cbp
& 3) << NV17_MPEG_CMD_CHROMA_MB_HEADER_CBP__SHIFT
;
194 nouveau_vpe_write(dec
, base_dct
);
195 nouveau_vpe_write(dec
, NV17_MPEG_CMD_MB_COORDS_OP_MB_COORDS
|
196 x
| (y
<< NV17_MPEG_CMD_MB_COORDS_Y__SHIFT
));
199 static INLINE
unsigned int
200 nouveau_vpe_mb_mv_flags(bool luma
, int mv_h
, int mv_v
, bool forward
, bool first
, bool vert
)
202 unsigned mc_header
= 0;
204 mc_header
|= NV17_MPEG_CMD_LUMA_MV_HEADER_OP_LUMA_MV_HEADER
;
206 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_OP_CHROMA_MV_HEADER
;
208 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_X_HALF
;
210 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_Y_HALF
;
212 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_DIRECTION_BACKWARD
;
214 mc_header
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_IDX
;
216 mc_header
|= NV17_MPEG_CMD_LUMA_MV_HEADER_FIELD_BOTTOM
;
220 static unsigned pos(int pos
, int mov
, int max
) {
229 /* because we want -1 / 2 = -1 */
230 static int div_down(int val
, int mult
) {
235 static int div_up(int val
, int mult
) {
241 nouveau_vpe_mb_mv(struct nouveau_decoder
*dec
, unsigned mc_header
,
242 bool luma
, bool frame
, bool forward
, bool vert
,
243 int x
, int y
, const short motions
[2],
244 unsigned surface
, bool first
)
247 int mv_horizontal
= motions
[0];
248 int mv_vertical
= motions
[1];
249 int mv2
= mc_header
& NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2
;
250 unsigned width
= dec
->base
.width
;
251 unsigned height
= dec
->base
.height
;
253 mv_vertical
= div_down(mv_vertical
, 2);
254 assert(frame
); // Untested for non-frames
258 mc_header
|= surface
<< NV17_MPEG_CMD_CHROMA_MV_HEADER_SURFACE__SHIFT
;
260 mv_vertical
= div_up(mv_vertical
, 2);
261 mv_horizontal
= div_up(mv_horizontal
, 2);
264 mc_header
|= nouveau_vpe_mb_mv_flags(luma
, mv_horizontal
, mv_vertical
, forward
, first
, vert
);
265 nouveau_vpe_write(dec
, mc_header
);
267 mc_vector
= NV17_MPEG_CMD_MV_COORDS_OP_MV_COORDS
;
269 mc_vector
|= pos(x
, div_down(mv_horizontal
, 2), width
);
271 mc_vector
|= pos(x
, mv_horizontal
& ~1, width
);
273 mc_vector
|= pos(y
, div_down(mv_vertical
, 2), height
) << NV17_MPEG_CMD_MV_COORDS_Y__SHIFT
;
275 mc_vector
|= pos(y
, mv_vertical
& ~1, height
) << NV17_MPEG_CMD_MV_COORDS_Y__SHIFT
;
276 nouveau_vpe_write(dec
, mc_vector
);
280 nouveau_vpe_mb_mv_header(struct nouveau_decoder
*dec
,
281 const struct pipe_mpeg12_macroblock
*mb
,
284 bool frame
= dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FRAME
;
286 bool forward
, backward
;
287 int y
, y2
, x
= mb
->x
* 16;
289 y
= mb
->y
* (frame
? 16 : 32);
291 y
= mb
->y
* (frame
? 8 : 16);
295 y2
= y
+ (luma
? 16 : 8);
297 forward
= mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_MOTION_FORWARD
;
298 backward
= mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD
;
299 assert(!forward
|| dec
->past
< 8);
300 assert(!backward
|| dec
->future
< 8);
302 switch (mb
->macroblock_modes
.bits
.frame_motion_type
) {
303 case PIPE_MPEG12_MO_TYPE_FRAME
: goto mv1
;
304 case PIPE_MPEG12_MO_TYPE_FIELD
: goto mv2
;
305 case PIPE_MPEG12_MO_TYPE_DUAL_PRIME
: {
306 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2
;
308 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
, FALSE
,
309 x
, y
, mb
->PMV
[0][0], dec
->past
, TRUE
);
310 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
, TRUE
,
311 x
, y2
, mb
->PMV
[0][0], dec
->past
, FALSE
);
313 if (backward
&& forward
) {
314 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
, TRUE
,
315 x
, y
, mb
->PMV
[1][0], dec
->future
, TRUE
);
316 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
, FALSE
,
317 x
, y2
, mb
->PMV
[1][1], dec
->future
, FALSE
);
318 } else assert(!backward
);
324 switch (mb
->macroblock_modes
.bits
.field_motion_type
) {
325 case PIPE_MPEG12_MO_TYPE_FIELD
: goto mv1
;
326 case PIPE_MPEG12_MO_TYPE_16x8
: goto mv2
;
327 case PIPE_MPEG12_MO_TYPE_DUAL_PRIME
: {
328 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB
;
330 base
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_TYPE_FRAME
;
332 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
,
333 dec
->picture_structure
!= PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_TOP
,
334 x
, y
, mb
->PMV
[0][0], dec
->past
, TRUE
);
335 if (backward
&& forward
)
336 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, FALSE
,
337 dec
->picture_structure
== PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_TOP
,
338 x
, y
, mb
->PMV
[0][1], dec
->future
, TRUE
);
339 else assert(!backward
);
348 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB
;
350 base
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_TYPE_FRAME
;
353 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
, FALSE
,
354 x
, y
, mb
->PMV
[0][0], dec
->past
, TRUE
);
356 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
, FALSE
,
357 x
, y
, mb
->PMV
[0][1], dec
->future
, TRUE
);
361 base
= NV17_MPEG_CMD_CHROMA_MV_HEADER_COUNT_2
;
363 base
|= NV17_MPEG_CMD_CHROMA_MV_HEADER_MV_SPLIT_HALF_MB
;
365 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
,
366 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_FIRST_FORWARD
,
367 x
, y
, mb
->PMV
[0][0], dec
->past
, TRUE
);
368 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, TRUE
,
369 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_SECOND_FORWARD
,
370 x
, y2
, mb
->PMV
[1][0], dec
->past
, FALSE
);
373 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
,
374 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_FIRST_BACKWARD
,
375 x
, y
, mb
->PMV
[0][1], dec
->future
, TRUE
);
376 nouveau_vpe_mb_mv(dec
, base
, luma
, frame
, !forward
,
377 mb
->motion_vertical_field_select
& PIPE_MPEG12_FS_SECOND_BACKWARD
,
378 x
, y2
, mb
->PMV
[1][1], dec
->future
, FALSE
);
383 nouveau_decoder_surface_index(struct nouveau_decoder
*dec
,
384 struct pipe_video_buffer
*buffer
)
386 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
387 struct nouveau_channel
*chan
= dec
->screen
->channel
;
388 struct nouveau_bo
*bo_y
= ((struct nv04_resource
*)buf
->resources
[0])->bo
;
389 struct nouveau_bo
*bo_c
= ((struct nv04_resource
*)buf
->resources
[1])->bo
;
394 for (i
= 0; i
< dec
->num_surfaces
; ++i
) {
395 if (dec
->surfaces
[i
] == buf
)
399 dec
->surfaces
[i
] = buf
;
402 MARK_RING(chan
, 3, 2);
403 BEGIN_RING(chan
, dec
->mpeg
, NV31_MPEG_IMAGE_Y_OFFSET(i
), 2);
404 OUT_RELOCl(chan
, bo_y
, 0, NOUVEAU_BO_RDWR
);
405 OUT_RELOCl(chan
, bo_c
, 0, NOUVEAU_BO_RDWR
);
410 nouveau_decoder_begin_frame(struct pipe_video_decoder
*decoder
,
411 struct pipe_video_buffer
*target
,
412 struct pipe_picture_desc
*picture
)
417 nouveau_decoder_decode_macroblock(struct pipe_video_decoder
*decoder
,
418 struct pipe_video_buffer
*target
,
419 struct pipe_picture_desc
*picture
,
420 const struct pipe_macroblock
*pipe_mb
,
421 unsigned num_macroblocks
)
423 struct nouveau_decoder
*dec
= (struct nouveau_decoder
*)decoder
;
424 struct pipe_mpeg12_picture_desc
*desc
= (struct pipe_mpeg12_picture_desc
*)picture
;
425 const struct pipe_mpeg12_macroblock
*mb
;
427 assert(target
->width
== decoder
->width
);
428 assert(target
->height
== decoder
->height
);
430 dec
->current
= nouveau_decoder_surface_index(dec
, target
);
431 assert(dec
->current
< 8);
432 dec
->picture_structure
= desc
->picture_structure
;
434 dec
->future
= nouveau_decoder_surface_index(dec
, desc
->ref
[1]);
436 dec
->past
= nouveau_decoder_surface_index(dec
, desc
->ref
[0]);
438 if (nouveau_vpe_init(dec
)) return;
439 mb
= (const struct pipe_mpeg12_macroblock
*)pipe_mb
;
440 for (i
= 0; i
< num_macroblocks
; ++i
, mb
++) {
441 if (mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
) {
442 nouveau_vpe_mb_dct_header(dec
, mb
, TRUE
);
443 nouveau_vpe_mb_dct_header(dec
, mb
, FALSE
);
445 nouveau_vpe_mb_mv_header(dec
, mb
, TRUE
);
446 nouveau_vpe_mb_dct_header(dec
, mb
, TRUE
);
448 nouveau_vpe_mb_mv_header(dec
, mb
, FALSE
);
449 nouveau_vpe_mb_dct_header(dec
, mb
, FALSE
);
451 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
452 nouveau_vpe_mb_dct_blocks(dec
, mb
);
454 nouveau_vpe_mb_data_blocks(dec
, mb
);
459 nouveau_decoder_end_frame(struct pipe_video_decoder
*decoder
,
460 struct pipe_video_buffer
*target
,
461 struct pipe_picture_desc
*picture
)
466 nouveau_decoder_flush(struct pipe_video_decoder
*decoder
)
468 struct nouveau_decoder
*dec
= (struct nouveau_decoder
*)decoder
;
470 nouveau_vpe_fini(dec
);
474 nouveau_decoder_destroy(struct pipe_video_decoder
*decoder
)
476 struct nouveau_decoder
*dec
= (struct nouveau_decoder
*)decoder
;
479 nouveau_bo_unmap(dec
->data_bo
);
480 nouveau_bo_unmap(dec
->cmd_bo
);
484 nouveau_bo_ref(NULL
, &dec
->data_bo
);
486 nouveau_bo_ref(NULL
, &dec
->cmd_bo
);
488 nouveau_bo_ref(NULL
, &dec
->fence_bo
);
489 nouveau_grobj_free(&dec
->mpeg
);
493 static struct pipe_video_decoder
*
494 nouveau_create_decoder(struct pipe_context
*context
,
495 struct nouveau_screen
*screen
,
496 enum pipe_video_profile profile
,
497 enum pipe_video_entrypoint entrypoint
,
498 enum pipe_video_chroma_format chroma_format
,
499 unsigned width
, unsigned height
,
500 unsigned max_references
, bool expect_chunked_decode
)
502 struct nouveau_channel
*chan
= screen
->channel
;
503 struct nouveau_grobj
*mpeg
= NULL
;
504 struct nouveau_decoder
*dec
;
506 bool is8274
= screen
->device
->chipset
> 0x80;
508 debug_printf("Acceleration level: %s\n", entrypoint
<= PIPE_VIDEO_ENTRYPOINT_BITSTREAM
? "bit":
509 entrypoint
== PIPE_VIDEO_ENTRYPOINT_IDCT
? "IDCT" : "MC");
511 if (getenv("XVMC_VL"))
513 if (u_reduce_video_profile(profile
) != PIPE_VIDEO_CODEC_MPEG12
)
515 if (screen
->device
->chipset
>= 0x98 && screen
->device
->chipset
!= 0xa0)
518 width
= align(width
, 64);
519 height
= align(height
, 64);
522 ret
= nouveau_grobj_alloc(chan
, 0xbeef8274, 0x8274, &mpeg
);
524 ret
= nouveau_grobj_alloc(chan
, 0xbeef8274, 0x3174, &mpeg
);
526 debug_printf("Creation failed: %s (%i)\n", strerror(-ret
), ret
);
530 dec
= CALLOC_STRUCT(nouveau_decoder
);
532 nouveau_grobj_free(&mpeg
);
536 dec
->base
.context
= context
;
537 dec
->base
.profile
= profile
;
538 dec
->base
.entrypoint
= entrypoint
;
539 dec
->base
.chroma_format
= chroma_format
;
540 dec
->base
.width
= width
;
541 dec
->base
.height
= height
;
542 dec
->base
.max_references
= max_references
;
543 dec
->base
.destroy
= nouveau_decoder_destroy
;
544 dec
->base
.begin_frame
= nouveau_decoder_begin_frame
;
545 dec
->base
.decode_macroblock
= nouveau_decoder_decode_macroblock
;
546 dec
->base
.begin_frame
= nouveau_decoder_end_frame
;
547 dec
->base
.flush
= nouveau_decoder_flush
;
548 dec
->screen
= screen
;
550 ret
= nouveau_bo_new(dec
->screen
->device
, NOUVEAU_BO_GART
, 0, 1024 * 1024, &dec
->cmd_bo
);
554 ret
= nouveau_bo_new(dec
->screen
->device
, NOUVEAU_BO_GART
, 0, width
* height
* 6, &dec
->data_bo
);
558 ret
= nouveau_bo_new(dec
->screen
->device
, NOUVEAU_BO_GART
|NOUVEAU_BO_MAP
, 0, 4096,
562 nouveau_bo_map(dec
->fence_bo
, NOUVEAU_BO_RDWR
);
563 dec
->fence_map
= dec
->fence_bo
->map
;
564 nouveau_bo_unmap(dec
->fence_bo
);
565 dec
->fence_map
[0] = 0;
568 MARK_RING(chan
, 25, 3);
570 MARK_RING(chan
, 20, 2);
572 BEGIN_RING(chan
, mpeg
, NV31_MPEG_DMA_CMD
, 1);
573 OUT_RING(chan
, chan
->vram
->handle
);
575 BEGIN_RING(chan
, mpeg
, NV31_MPEG_DMA_DATA
, 1);
576 OUT_RING(chan
, chan
->vram
->handle
);
578 BEGIN_RING(chan
, mpeg
, NV31_MPEG_DMA_IMAGE
, 1);
579 OUT_RING(chan
, chan
->vram
->handle
);
581 BEGIN_RING(chan
, mpeg
, NV31_MPEG_PITCH
, 2);
582 OUT_RING(chan
, width
| NV31_MPEG_PITCH_UNK
);
583 OUT_RING(chan
, (height
<< NV31_MPEG_SIZE_H__SHIFT
) | width
);
585 BEGIN_RING(chan
, mpeg
, NV31_MPEG_FORMAT
, 2);
587 switch (entrypoint
) {
588 case PIPE_VIDEO_ENTRYPOINT_BITSTREAM
: OUT_RING(chan
, 0x100); break;
589 case PIPE_VIDEO_ENTRYPOINT_IDCT
: OUT_RING(chan
, 1); break;
590 case PIPE_VIDEO_ENTRYPOINT_MC
: OUT_RING(chan
, 0); break;
595 BEGIN_RING(chan
, mpeg
, NV84_MPEG_DMA_QUERY
, 1);
596 OUT_RING(chan
, chan
->vram
->handle
);
598 BEGIN_RING(chan
, mpeg
, NV84_MPEG_QUERY_OFFSET
, 2);
599 OUT_RELOCl(chan
, dec
->fence_bo
, 0, NOUVEAU_BO_WR
|NOUVEAU_BO_GART
);
600 OUT_RING(chan
, dec
->fence_seq
);
603 ret
= nouveau_vpe_init(dec
);
606 nouveau_vpe_fini(dec
);
610 nouveau_decoder_destroy(&dec
->base
);
614 debug_printf("Using g3dvl renderer\n");
615 return vl_create_decoder(context
, profile
, entrypoint
,
616 chroma_format
, width
, height
,
617 max_references
, expect_chunked_decode
);
620 static struct pipe_sampler_view
**
621 nouveau_video_buffer_sampler_view_planes(struct pipe_video_buffer
*buffer
)
623 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
624 struct pipe_sampler_view sv_templ
;
625 struct pipe_context
*pipe
;
630 pipe
= buf
->base
.context
;
632 for (i
= 0; i
< buf
->num_planes
; ++i
) {
633 if (!buf
->sampler_view_planes
[i
]) {
634 memset(&sv_templ
, 0, sizeof(sv_templ
));
635 u_sampler_view_default_template(&sv_templ
, buf
->resources
[i
], buf
->resources
[i
]->format
);
637 if (util_format_get_nr_components(buf
->resources
[i
]->format
) == 1)
638 sv_templ
.swizzle_r
= sv_templ
.swizzle_g
= sv_templ
.swizzle_b
= sv_templ
.swizzle_a
= PIPE_SWIZZLE_RED
;
640 buf
->sampler_view_planes
[i
] = pipe
->create_sampler_view(pipe
, buf
->resources
[i
], &sv_templ
);
641 if (!buf
->sampler_view_planes
[i
])
646 return buf
->sampler_view_planes
;
649 for (i
= 0; i
< buf
->num_planes
; ++i
)
650 pipe_sampler_view_reference(&buf
->sampler_view_planes
[i
], NULL
);
655 static struct pipe_sampler_view
**
656 nouveau_video_buffer_sampler_view_components(struct pipe_video_buffer
*buffer
)
658 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
659 struct pipe_sampler_view sv_templ
;
660 struct pipe_context
*pipe
;
661 unsigned i
, j
, component
;
665 pipe
= buf
->base
.context
;
667 for (component
= 0, i
= 0; i
< buf
->num_planes
; ++i
) {
668 unsigned nr_components
= util_format_get_nr_components(buf
->resources
[i
]->format
);
670 for (j
= 0; j
< nr_components
; ++j
, ++component
) {
671 assert(component
< VL_NUM_COMPONENTS
);
673 if (!buf
->sampler_view_components
[component
]) {
674 memset(&sv_templ
, 0, sizeof(sv_templ
));
675 u_sampler_view_default_template(&sv_templ
, buf
->resources
[i
], buf
->resources
[i
]->format
);
676 sv_templ
.swizzle_r
= sv_templ
.swizzle_g
= sv_templ
.swizzle_b
= PIPE_SWIZZLE_RED
+ j
;
677 sv_templ
.swizzle_a
= PIPE_SWIZZLE_ONE
;
678 buf
->sampler_view_components
[component
] = pipe
->create_sampler_view(pipe
, buf
->resources
[i
], &sv_templ
);
679 if (!buf
->sampler_view_components
[component
])
685 return buf
->sampler_view_components
;
688 for (i
= 0; i
< 3; ++i
)
689 pipe_sampler_view_reference(&buf
->sampler_view_components
[i
], NULL
);
694 static struct pipe_surface
**
695 nouveau_video_buffer_surfaces(struct pipe_video_buffer
*buffer
)
697 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
698 struct pipe_surface surf_templ
;
699 struct pipe_context
*pipe
;
704 pipe
= buf
->base
.context
;
706 for (i
= 0; i
< buf
->num_planes
; ++i
) {
707 if (!buf
->surfaces
[i
]) {
708 memset(&surf_templ
, 0, sizeof(surf_templ
));
709 surf_templ
.format
= buf
->resources
[i
]->format
;
710 surf_templ
.usage
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
711 buf
->surfaces
[i
] = pipe
->create_surface(pipe
, buf
->resources
[i
], &surf_templ
);
712 if (!buf
->surfaces
[i
])
717 return buf
->surfaces
;
720 for (i
= 0; i
< buf
->num_planes
; ++i
)
721 pipe_surface_reference(&buf
->surfaces
[i
], NULL
);
727 nouveau_video_buffer_destroy(struct pipe_video_buffer
*buffer
)
729 struct nouveau_video_buffer
*buf
= (struct nouveau_video_buffer
*)buffer
;
734 for (i
= 0; i
< buf
->num_planes
; ++i
) {
735 pipe_surface_reference(&buf
->surfaces
[i
], NULL
);
736 pipe_sampler_view_reference(&buf
->sampler_view_planes
[i
], NULL
);
737 pipe_sampler_view_reference(&buf
->sampler_view_components
[i
], NULL
);
738 pipe_resource_reference(&buf
->resources
[i
], NULL
);
741 pipe_sampler_view_reference(&buf
->sampler_view_components
[i
], NULL
);
746 static struct pipe_video_buffer
*
747 nouveau_video_buffer_create(struct pipe_context
*pipe
,
748 struct nouveau_screen
*screen
,
749 const struct pipe_video_buffer
*templat
)
751 struct nouveau_video_buffer
*buffer
;
752 struct pipe_resource templ
;
753 unsigned width
, height
;
755 /* Only do a linear surface when a hardware decoder is used
756 * hardware decoder is only supported on some chipsets
757 * and it only supports the NV12 format
759 if (templat
->buffer_format
!= PIPE_FORMAT_NV12
|| getenv("XVMC_VL") ||
760 (screen
->device
->chipset
>= 0x98 && screen
->device
->chipset
!= 0xa0))
761 return vl_video_buffer_create(pipe
, templat
);
763 assert(templat
->chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
764 width
= align(templat
->width
, 64);
765 height
= align(templat
->height
, 64);
767 buffer
= CALLOC_STRUCT(nouveau_video_buffer
);
771 buffer
->base
.context
= pipe
;
772 buffer
->base
.destroy
= nouveau_video_buffer_destroy
;
773 buffer
->base
.get_sampler_view_planes
= nouveau_video_buffer_sampler_view_planes
;
774 buffer
->base
.get_sampler_view_components
= nouveau_video_buffer_sampler_view_components
;
775 buffer
->base
.get_surfaces
= nouveau_video_buffer_surfaces
;
776 buffer
->base
.chroma_format
= templat
->chroma_format
;
777 buffer
->base
.width
= width
;
778 buffer
->base
.height
= height
;
779 buffer
->num_planes
= 2;
781 memset(&templ
, 0, sizeof(templ
));
782 templ
.target
= PIPE_TEXTURE_2D
;
783 templ
.format
= PIPE_FORMAT_R8_UNORM
;
784 templ
.width0
= width
;
785 templ
.height0
= height
;
787 templ
.array_size
= 1;
788 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
789 templ
.usage
= PIPE_USAGE_STATIC
;
790 templ
.flags
= NOUVEAU_RESOURCE_FLAG_LINEAR
;
792 buffer
->resources
[0] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
793 if (!buffer
->resources
[0])
797 templ
.format
= PIPE_FORMAT_R8G8_UNORM
;
798 buffer
->resources
[1] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
799 if (!buffer
->resources
[1])
801 return &buffer
->base
;
804 nouveau_video_buffer_destroy(&buffer
->base
);
809 nouveau_screen_get_video_param(struct pipe_screen
*pscreen
,
810 enum pipe_video_profile profile
,
811 enum pipe_video_cap param
)
814 case PIPE_VIDEO_CAP_SUPPORTED
:
815 return vl_profile_supported(pscreen
, profile
);
816 case PIPE_VIDEO_CAP_NPOT_TEXTURES
:
818 case PIPE_VIDEO_CAP_MAX_WIDTH
:
819 case PIPE_VIDEO_CAP_MAX_HEIGHT
:
820 return vl_video_buffer_max_size(pscreen
);
821 case PIPE_VIDEO_CAP_PREFERED_FORMAT
:
822 return PIPE_FORMAT_NV12
;
823 case PIPE_VIDEO_CAP_PREFERS_INTERLACED
:
825 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED
:
827 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE
:
830 debug_printf("unknown video param: %d\n", param
);
836 nouveau_screen_init_vdec(struct nouveau_screen
*screen
)
838 screen
->base
.get_video_param
= nouveau_screen_get_video_param
;
839 screen
->base
.is_video_format_supported
= vl_video_buffer_is_format_supported
;
842 static struct pipe_video_decoder
*
843 nouveau_context_create_decoder(struct pipe_context
*context
,
844 enum pipe_video_profile profile
,
845 enum pipe_video_entrypoint entrypoint
,
846 enum pipe_video_chroma_format chroma_format
,
847 unsigned width
, unsigned height
,
848 unsigned max_references
, bool expect_chunked_decode
)
850 struct nouveau_screen
*screen
= nouveau_context(context
)->screen
;
851 return nouveau_create_decoder(context
, screen
, profile
, entrypoint
,
852 chroma_format
, width
, height
,
853 max_references
, expect_chunked_decode
);
856 static struct pipe_video_buffer
*
857 nouveau_context_video_buffer_create(struct pipe_context
*pipe
,
858 const struct pipe_video_buffer
*templat
)
860 struct nouveau_screen
*screen
= nouveau_context(pipe
)->screen
;
861 return nouveau_video_buffer_create(pipe
, screen
, templat
);
865 nouveau_context_init_vdec(struct nouveau_context
*nv
)
867 nv
->pipe
.create_video_decoder
= nouveau_context_create_decoder
;
868 nv
->pipe
.create_video_buffer
= nouveau_context_video_buffer_create
;