diff options
author | Ilia Mirkin <imirkin@alum.mit.edu> | 2013-08-10 20:19:24 -0400 |
---|---|---|
committer | Maarten Lankhorst <maarten.lankhorst@canonical.com> | 2013-08-16 09:48:47 +0200 |
commit | a2061eea0f89b44c816e6c7570b983e8cfda41cd (patch) | |
tree | df7ea1084a69bc4c20b8ef2c11df611613756283 | |
parent | b3f6f127f28737d034dcf1c12a9b66b88750e93b (diff) |
nv50: add vp3/vp4 support for mpeg2/vc1
h264/mpeg4 remain disabled for pre-nvc0, there's some minor
bug/difference which causes the decoding to hang after some frames.
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
-rw-r--r-- | src/gallium/drivers/nouveau/nouveau_vp3_video.c | 39 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/Makefile.sources | 6 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_context.c | 5 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_context.h | 14 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_screen.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_winsys.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv84_video.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv98_video.c | 308 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv98_video.h | 48 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv98_video_bsp.c | 159 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv98_video_ppp.c | 143 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv98_video_vp.c | 202 |
12 files changed, 927 insertions, 12 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_vp3_video.c b/src/gallium/drivers/nouveau/nouveau_vp3_video.c index dc75219eee4..36fea5879d0 100644 --- a/src/gallium/drivers/nouveau/nouveau_vp3_video.c +++ b/src/gallium/drivers/nouveau/nouveau_vp3_video.c | |||
@@ -231,6 +231,25 @@ nouveau_vp3_decoder_init_common(struct pipe_video_decoder *dec) | |||
231 | dec->end_frame = nouveau_vp3_decoder_end_frame; | 231 | dec->end_frame = nouveau_vp3_decoder_end_frame; |
232 | } | 232 | } |
233 | 233 | ||
234 | static void vp3_getpath(enum pipe_video_profile profile, char *path) | ||
235 | { | ||
236 | switch (u_reduce_video_profile(profile)) { | ||
237 | case PIPE_VIDEO_CODEC_MPEG12: { | ||
238 | sprintf(path, "/lib/firmware/nouveau/vuc-vp3-mpeg12-0"); | ||
239 | break; | ||
240 | } | ||
241 | case PIPE_VIDEO_CODEC_VC1: { | ||
242 | sprintf(path, "/lib/firmware/nouveau/vuc-vp3-vc1-0"); | ||
243 | break; | ||
244 | } | ||
245 | case PIPE_VIDEO_CODEC_MPEG4_AVC: { | ||
246 | sprintf(path, "/lib/firmware/nouveau/vuc-vp3-h264-0"); | ||
247 | break; | ||
248 | } | ||
249 | default: assert(0); | ||
250 | } | ||
251 | } | ||
252 | |||
234 | static void vp4_getpath(enum pipe_video_profile profile, char *path) | 253 | static void vp4_getpath(enum pipe_video_profile profile, char *path) |
235 | { | 254 | { |
236 | switch (u_reduce_video_profile(profile)) { | 255 | switch (u_reduce_video_profile(profile)) { |
@@ -264,7 +283,10 @@ nouveau_vp3_load_firmware(struct nouveau_vp3_decoder *dec, | |||
264 | ssize_t r; | 283 | ssize_t r; |
265 | uint32_t *end, endval; | 284 | uint32_t *end, endval; |
266 | 285 | ||
267 | vp4_getpath(profile, path); | 286 | if (chipset >= 0xa3 && chipset != 0xaa && chipset != 0xac) |
287 | vp4_getpath(profile, path); | ||
288 | else | ||
289 | vp3_getpath(profile, path); | ||
268 | 290 | ||
269 | if (nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client)) | 291 | if (nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client)) |
270 | return 1; | 292 | return 1; |
@@ -333,14 +355,25 @@ nouveau_vp3_screen_get_video_param(struct pipe_screen *pscreen, | |||
333 | enum pipe_video_profile profile, | 355 | enum pipe_video_profile profile, |
334 | enum pipe_video_cap param) | 356 | enum pipe_video_cap param) |
335 | { | 357 | { |
358 | int chipset = nouveau_screen(pscreen)->device->chipset; | ||
359 | int vp3 = chipset < 0xa3 || chipset == 0xaa || chipset == 0xac; | ||
360 | int vp5 = chipset >= 0xd0; | ||
361 | enum pipe_video_codec codec = u_reduce_video_profile(profile); | ||
336 | switch (param) { | 362 | switch (param) { |
337 | case PIPE_VIDEO_CAP_SUPPORTED: | 363 | case PIPE_VIDEO_CAP_SUPPORTED: |
338 | return profile >= PIPE_VIDEO_PROFILE_MPEG1; | 364 | /* For now, h264 and mpeg4 don't work on pre-nvc0. */ |
365 | if (chipset < 0xc0) | ||
366 | return codec == PIPE_VIDEO_CODEC_MPEG12 || | ||
367 | codec == PIPE_VIDEO_CODEC_VC1; | ||
368 | /* In the general case, this should work, once the pre-nvc0 problems are | ||
369 | * resolved. */ | ||
370 | return profile >= PIPE_VIDEO_PROFILE_MPEG1 && ( | ||
371 | !vp3 || codec != PIPE_VIDEO_CODEC_MPEG4); | ||
339 | case PIPE_VIDEO_CAP_NPOT_TEXTURES: | 372 | case PIPE_VIDEO_CAP_NPOT_TEXTURES: |
340 | return 1; | 373 | return 1; |
341 | case PIPE_VIDEO_CAP_MAX_WIDTH: | 374 | case PIPE_VIDEO_CAP_MAX_WIDTH: |
342 | case PIPE_VIDEO_CAP_MAX_HEIGHT: | 375 | case PIPE_VIDEO_CAP_MAX_HEIGHT: |
343 | return nouveau_screen(pscreen)->device->chipset < 0xd0 ? 2048 : 4096; | 376 | return vp5 ? 4096 : 2048; |
344 | case PIPE_VIDEO_CAP_PREFERED_FORMAT: | 377 | case PIPE_VIDEO_CAP_PREFERED_FORMAT: |
345 | return PIPE_FORMAT_NV12; | 378 | return PIPE_FORMAT_NV12; |
346 | case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: | 379 | case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: |
diff --git a/src/gallium/drivers/nv50/Makefile.sources b/src/gallium/drivers/nv50/Makefile.sources index 0fdac5189aa..9a2d1024823 100644 --- a/src/gallium/drivers/nv50/Makefile.sources +++ b/src/gallium/drivers/nv50/Makefile.sources | |||
@@ -16,7 +16,11 @@ C_SOURCES := \ | |||
16 | nv50_query.c \ | 16 | nv50_query.c \ |
17 | nv84_video.c \ | 17 | nv84_video.c \ |
18 | nv84_video_bsp.c \ | 18 | nv84_video_bsp.c \ |
19 | nv84_video_vp.c | 19 | nv84_video_vp.c \ |
20 | nv98_video.c \ | ||
21 | nv98_video_bsp.c \ | ||
22 | nv98_video_vp.c \ | ||
23 | nv98_video_ppp.c | ||
20 | 24 | ||
21 | CODEGEN_NV50_SOURCES := \ | 25 | CODEGEN_NV50_SOURCES := \ |
22 | codegen/nv50_ir.cpp \ | 26 | codegen/nv50_ir.cpp \ |
diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 185d241e70f..0ed9d8f1839 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c | |||
@@ -268,8 +268,9 @@ nv50_create(struct pipe_screen *pscreen, void *priv) | |||
268 | pipe->create_video_decoder = nv84_create_decoder; | 268 | pipe->create_video_decoder = nv84_create_decoder; |
269 | pipe->create_video_buffer = nv84_video_buffer_create; | 269 | pipe->create_video_buffer = nv84_video_buffer_create; |
270 | } else { | 270 | } else { |
271 | /* Unsupported, but need to init pointers. */ | 271 | /* VP3/4 */ |
272 | nouveau_context_init_vdec(&nv50->base); | 272 | pipe->create_video_decoder = nv98_create_decoder; |
273 | pipe->create_video_buffer = nv98_video_buffer_create; | ||
273 | } | 274 | } |
274 | 275 | ||
275 | flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; | 276 | flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; |
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index b204cc8b9c1..52a1aa5147d 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h | |||
@@ -313,4 +313,18 @@ nv84_screen_video_supported(struct pipe_screen *screen, | |||
313 | enum pipe_format format, | 313 | enum pipe_format format, |
314 | enum pipe_video_profile profile); | 314 | enum pipe_video_profile profile); |
315 | 315 | ||
316 | /* nv98_video.c */ | ||
317 | struct pipe_video_decoder * | ||
318 | nv98_create_decoder(struct pipe_context *context, | ||
319 | enum pipe_video_profile profile, | ||
320 | enum pipe_video_entrypoint entrypoint, | ||
321 | enum pipe_video_chroma_format chroma_format, | ||
322 | unsigned width, unsigned height, | ||
323 | unsigned max_references, | ||
324 | bool expect_chunked_decode); | ||
325 | |||
326 | struct pipe_video_buffer * | ||
327 | nv98_video_buffer_create(struct pipe_context *pipe, | ||
328 | const struct pipe_video_buffer *template); | ||
329 | |||
316 | #endif | 330 | #endif |
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 0cbee5d677b..1f52594abbd 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include "nv50_context.h" | 27 | #include "nv50_context.h" |
28 | #include "nv50_screen.h" | 28 | #include "nv50_screen.h" |
29 | 29 | ||
30 | #include "nouveau/nouveau_vp3_video.h" | ||
31 | |||
30 | #include "nouveau/nv_object.xml.h" | 32 | #include "nouveau/nv_object.xml.h" |
31 | #include <errno.h> | 33 | #include <errno.h> |
32 | 34 | ||
@@ -657,8 +659,9 @@ nv50_screen_create(struct nouveau_device *dev) | |||
657 | screen->base.base.get_video_param = nv84_screen_get_video_param; | 659 | screen->base.base.get_video_param = nv84_screen_get_video_param; |
658 | screen->base.base.is_video_format_supported = nv84_screen_video_supported; | 660 | screen->base.base.is_video_format_supported = nv84_screen_video_supported; |
659 | } else { | 661 | } else { |
660 | /* Unsupported, but need to init pointers. */ | 662 | /* VP3/4 */ |
661 | nouveau_screen_init_vdec(&screen->base); | 663 | screen->base.base.get_video_param = nouveau_vp3_screen_get_video_param; |
664 | screen->base.base.is_video_format_supported = nouveau_vp3_screen_video_supported; | ||
662 | } | 665 | } |
663 | 666 | ||
664 | ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096, | 667 | ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096, |
diff --git a/src/gallium/drivers/nv50/nv50_winsys.h b/src/gallium/drivers/nv50/nv50_winsys.h index e04247b0118..145ee70cb9f 100644 --- a/src/gallium/drivers/nv50/nv50_winsys.h +++ b/src/gallium/drivers/nv50/nv50_winsys.h | |||
@@ -60,10 +60,6 @@ PUSH_REFN(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t flags) | |||
60 | #define SUBC_COMPUTE(m) 6, (m) | 60 | #define SUBC_COMPUTE(m) 6, (m) |
61 | #define NV50_COMPUTE(n) SUBC_COMPUTE(NV50_COMPUTE_##n) | 61 | #define NV50_COMPUTE(n) SUBC_COMPUTE(NV50_COMPUTE_##n) |
62 | 62 | ||
63 | /* These are expected to be on their own pushbufs */ | ||
64 | #define SUBC_BSP(m) 2, (m) | ||
65 | #define SUBC_VP(m) 2, (m) | ||
66 | |||
67 | 63 | ||
68 | static INLINE uint32_t | 64 | static INLINE uint32_t |
69 | NV50_FIFO_PKHDR(int subc, int mthd, unsigned size) | 65 | NV50_FIFO_PKHDR(int subc, int mthd, unsigned size) |
diff --git a/src/gallium/drivers/nv50/nv84_video.h b/src/gallium/drivers/nv50/nv84_video.h index 4ff8cf32765..4240cef6564 100644 --- a/src/gallium/drivers/nv50/nv84_video.h +++ b/src/gallium/drivers/nv50/nv84_video.h | |||
@@ -33,6 +33,10 @@ | |||
33 | 33 | ||
34 | #include "nv50_context.h" | 34 | #include "nv50_context.h" |
35 | 35 | ||
36 | /* These are expected to be on their own pushbufs */ | ||
37 | #define SUBC_BSP(m) 2, (m) | ||
38 | #define SUBC_VP(m) 2, (m) | ||
39 | |||
36 | union pipe_desc { | 40 | union pipe_desc { |
37 | struct pipe_picture_desc *base; | 41 | struct pipe_picture_desc *base; |
38 | struct pipe_mpeg12_picture_desc *mpeg12; | 42 | struct pipe_mpeg12_picture_desc *mpeg12; |
diff --git a/src/gallium/drivers/nv50/nv98_video.c b/src/gallium/drivers/nv50/nv98_video.c new file mode 100644 index 00000000000..f16fbd07a9d --- /dev/null +++ b/src/gallium/drivers/nv50/nv98_video.c | |||
@@ -0,0 +1,308 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2013 Maarten Lankhorst, Ilia Mirkin | ||
3 | * | ||
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: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
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. | ||
21 | */ | ||
22 | |||
23 | #include "nv98_video.h" | ||
24 | |||
25 | #include "util/u_sampler.h" | ||
26 | #include "util/u_format.h" | ||
27 | |||
28 | static void | ||
29 | nv98_decoder_decode_bitstream(struct pipe_video_decoder *decoder, | ||
30 | struct pipe_video_buffer *video_target, | ||
31 | struct pipe_picture_desc *picture, | ||
32 | unsigned num_buffers, | ||
33 | const void *const *data, | ||
34 | const unsigned *num_bytes) | ||
35 | { | ||
36 | struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder; | ||
37 | struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target; | ||
38 | uint32_t comm_seq = ++dec->fence_seq; | ||
39 | union pipe_desc desc; | ||
40 | |||
41 | unsigned vp_caps, is_ref, ret; | ||
42 | struct nouveau_vp3_video_buffer *refs[16] = {}; | ||
43 | |||
44 | desc.base = picture; | ||
45 | |||
46 | assert(target->base.buffer_format == PIPE_FORMAT_NV12); | ||
47 | |||
48 | ret = nv98_decoder_bsp(dec, desc, target, comm_seq, | ||
49 | num_buffers, data, num_bytes, | ||
50 | &vp_caps, &is_ref, refs); | ||
51 | |||
52 | /* did we decode bitstream correctly? */ | ||
53 | assert(ret == 2); | ||
54 | |||
55 | nv98_decoder_vp(dec, desc, target, comm_seq, vp_caps, is_ref, refs); | ||
56 | nv98_decoder_ppp(dec, desc, target, comm_seq); | ||
57 | } | ||
58 | |||
59 | struct pipe_video_decoder * | ||
60 | nv98_create_decoder(struct pipe_context *context, | ||
61 | enum pipe_video_profile profile, | ||
62 | enum pipe_video_entrypoint entrypoint, | ||
63 | enum pipe_video_chroma_format chroma_format, | ||
64 | unsigned width, unsigned height, unsigned max_references, | ||
65 | bool chunked_decode) | ||
66 | { | ||
67 | struct nouveau_screen *screen = &((struct nv50_context *)context)->screen->base; | ||
68 | struct nouveau_vp3_decoder *dec; | ||
69 | struct nouveau_pushbuf **push; | ||
70 | struct nv04_fifo nv04_data = {.vram = 0xbeef0201, .gart = 0xbeef0202}; | ||
71 | union nouveau_bo_config cfg; | ||
72 | |||
73 | cfg.nv50.tile_mode = 0x20; | ||
74 | cfg.nv50.memtype = 0x70; | ||
75 | |||
76 | int ret, i; | ||
77 | uint32_t codec = 1, ppp_codec = 3; | ||
78 | uint32_t timeout; | ||
79 | u32 tmp_size = 0; | ||
80 | |||
81 | if (getenv("XVMC_VL")) | ||
82 | return vl_create_decoder(context, profile, entrypoint, | ||
83 | chroma_format, width, height, | ||
84 | max_references, chunked_decode); | ||
85 | |||
86 | if (entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) { | ||
87 | debug_printf("%x\n", entrypoint); | ||
88 | return NULL; | ||
89 | } | ||
90 | |||
91 | dec = CALLOC_STRUCT(nouveau_vp3_decoder); | ||
92 | if (!dec) | ||
93 | return NULL; | ||
94 | dec->client = screen->client; | ||
95 | nouveau_vp3_decoder_init_common(&dec->base); | ||
96 | |||
97 | dec->bsp_idx = 5; | ||
98 | dec->vp_idx = 6; | ||
99 | dec->ppp_idx = 7; | ||
100 | |||
101 | ret = nouveau_object_new(&screen->device->object, 0, | ||
102 | NOUVEAU_FIFO_CHANNEL_CLASS, | ||
103 | &nv04_data, sizeof(nv04_data), &dec->channel[0]); | ||
104 | |||
105 | if (!ret) | ||
106 | ret = nouveau_pushbuf_new(screen->client, dec->channel[0], 4, | ||
107 | 32 * 1024, true, &dec->pushbuf[0]); | ||
108 | |||
109 | for (i = 1; i < 3; ++i) { | ||
110 | dec->channel[i] = dec->channel[0]; | ||
111 | dec->pushbuf[i] = dec->pushbuf[0]; | ||
112 | } | ||
113 | push = dec->pushbuf; | ||
114 | |||
115 | if (!ret) | ||
116 | ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x85b1, NULL, 0, &dec->bsp); | ||
117 | if (!ret) | ||
118 | ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x85b2, NULL, 0, &dec->vp); | ||
119 | if (!ret) | ||
120 | ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x85b3, NULL, 0, &dec->ppp); | ||
121 | if (ret) | ||
122 | goto fail; | ||
123 | |||
124 | BEGIN_NV04(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1); | ||
125 | PUSH_DATA (push[0], dec->bsp->handle); | ||
126 | |||
127 | BEGIN_NV04(push[0], SUBC_BSP(0x180), 5); | ||
128 | for (i = 0; i < 5; i++) | ||
129 | PUSH_DATA (push[0], nv04_data.vram); | ||
130 | |||
131 | BEGIN_NV04(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1); | ||
132 | PUSH_DATA (push[1], dec->vp->handle); | ||
133 | |||
134 | BEGIN_NV04(push[1], SUBC_VP(0x180), 6); | ||
135 | for (i = 0; i < 6; i++) | ||
136 | PUSH_DATA (push[1], nv04_data.vram); | ||
137 | |||
138 | BEGIN_NV04(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1); | ||
139 | PUSH_DATA (push[2], dec->ppp->handle); | ||
140 | |||
141 | BEGIN_NV04(push[2], SUBC_PPP(0x180), 5); | ||
142 | for (i = 0; i < 5; i++) | ||
143 | PUSH_DATA (push[2], nv04_data.vram); | ||
144 | |||
145 | dec->base.context = context; | ||
146 | dec->base.profile = profile; | ||
147 | dec->base.entrypoint = entrypoint; | ||
148 | dec->base.chroma_format = chroma_format; | ||
149 | dec->base.width = width; | ||
150 | dec->base.height = height; | ||
151 | dec->base.max_references = max_references; | ||
152 | dec->base.decode_bitstream = nv98_decoder_decode_bitstream; | ||
153 | |||
154 | for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i) | ||
155 | ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, | ||
156 | 0, 1 << 20, NULL, &dec->bsp_bo[i]); | ||
157 | if (!ret) | ||
158 | ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, | ||
159 | 0x100, 4 << 20, NULL, &dec->inter_bo[0]); | ||
160 | if (!ret) | ||
161 | nouveau_bo_ref(dec->inter_bo[0], &dec->inter_bo[1]); | ||
162 | if (ret) | ||
163 | goto fail; | ||
164 | |||
165 | switch (u_reduce_video_profile(profile)) { | ||
166 | case PIPE_VIDEO_CODEC_MPEG12: { | ||
167 | codec = 1; | ||
168 | assert(max_references <= 2); | ||
169 | break; | ||
170 | } | ||
171 | case PIPE_VIDEO_CODEC_MPEG4: { | ||
172 | codec = 4; | ||
173 | tmp_size = mb(height)*16 * mb(width)*16; | ||
174 | assert(max_references <= 2); | ||
175 | break; | ||
176 | } | ||
177 | case PIPE_VIDEO_CODEC_VC1: { | ||
178 | ppp_codec = codec = 2; | ||
179 | tmp_size = mb(height)*16 * mb(width)*16; | ||
180 | assert(max_references <= 2); | ||
181 | break; | ||
182 | } | ||
183 | case PIPE_VIDEO_CODEC_MPEG4_AVC: { | ||
184 | codec = 3; | ||
185 | dec->tmp_stride = 16 * mb_half(width) * nouveau_vp3_video_align(height) * 3 / 2; | ||
186 | tmp_size = dec->tmp_stride * (max_references + 1); | ||
187 | assert(max_references <= 16); | ||
188 | break; | ||
189 | } | ||
190 | default: | ||
191 | fprintf(stderr, "invalid codec\n"); | ||
192 | goto fail; | ||
193 | } | ||
194 | |||
195 | ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0, | ||
196 | 0x4000, NULL, &dec->fw_bo); | ||
197 | if (ret) | ||
198 | goto fail; | ||
199 | |||
200 | ret = nouveau_vp3_load_firmware(dec, profile, screen->device->chipset); | ||
201 | if (ret) | ||
202 | goto fw_fail; | ||
203 | |||
204 | if (codec != 3) { | ||
205 | ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0, | ||
206 | 0x400, NULL, &dec->bitplane_bo); | ||
207 | if (ret) | ||
208 | goto fail; | ||
209 | } | ||
210 | |||
211 | dec->ref_stride = mb(width)*16 * (mb_half(height)*32 + nouveau_vp3_video_align(height)/2); | ||
212 | ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0, | ||
213 | dec->ref_stride * (max_references+2) + tmp_size, | ||
214 | &cfg, &dec->ref_bo); | ||
215 | if (ret) | ||
216 | goto fail; | ||
217 | |||
218 | timeout = 0; | ||
219 | |||
220 | BEGIN_NV04(push[0], SUBC_BSP(0x200), 2); | ||
221 | PUSH_DATA (push[0], codec); | ||
222 | PUSH_DATA (push[0], timeout); | ||
223 | |||
224 | BEGIN_NV04(push[1], SUBC_VP(0x200), 2); | ||
225 | PUSH_DATA (push[1], codec); | ||
226 | PUSH_DATA (push[1], timeout); | ||
227 | |||
228 | BEGIN_NV04(push[2], SUBC_PPP(0x200), 2); | ||
229 | PUSH_DATA (push[2], ppp_codec); | ||
230 | PUSH_DATA (push[2], timeout); | ||
231 | |||
232 | ++dec->fence_seq; | ||
233 | |||
234 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
235 | ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP, | ||
236 | 0, 0x1000, NULL, &dec->fence_bo); | ||
237 | if (ret) | ||
238 | goto fail; | ||
239 | |||
240 | nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client); | ||
241 | dec->fence_map = dec->fence_bo->map; | ||
242 | dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0; | ||
243 | dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map))); | ||
244 | |||
245 | /* So lets test if the fence is working? */ | ||
246 | nouveau_pushbuf_space(push[0], 6, 1, 0); | ||
247 | PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); | ||
248 | BEGIN_NV04(push[0], SUBC_BSP(0x240), 3); | ||
249 | PUSH_DATAh(push[0], dec->fence_bo->offset); | ||
250 | PUSH_DATA (push[0], dec->fence_bo->offset); | ||
251 | PUSH_DATA (push[0], dec->fence_seq); | ||
252 | |||
253 | BEGIN_NV04(push[0], SUBC_BSP(0x304), 1); | ||
254 | PUSH_DATA (push[0], 0); | ||
255 | PUSH_KICK (push[0]); | ||
256 | |||
257 | nouveau_pushbuf_space(push[1], 6, 1, 0); | ||
258 | PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); | ||
259 | BEGIN_NV04(push[1], SUBC_VP(0x240), 3); | ||
260 | PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10)); | ||
261 | PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10)); | ||
262 | PUSH_DATA (push[1], dec->fence_seq); | ||
263 | |||
264 | BEGIN_NV04(push[1], SUBC_VP(0x304), 1); | ||
265 | PUSH_DATA (push[1], 0); | ||
266 | PUSH_KICK (push[1]); | ||
267 | |||
268 | nouveau_pushbuf_space(push[2], 6, 1, 0); | ||
269 | PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR); | ||
270 | BEGIN_NV04(push[2], SUBC_PPP(0x240), 3); | ||
271 | PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20)); | ||
272 | PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20)); | ||
273 | PUSH_DATA (push[2], dec->fence_seq); | ||
274 | |||
275 | BEGIN_NV04(push[2], SUBC_PPP(0x304), 1); | ||
276 | PUSH_DATA (push[2], 0); | ||
277 | PUSH_KICK (push[2]); | ||
278 | |||
279 | usleep(100); | ||
280 | while (dec->fence_seq > dec->fence_map[0] || | ||
281 | dec->fence_seq > dec->fence_map[4] || | ||
282 | dec->fence_seq > dec->fence_map[8]) { | ||
283 | debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]); | ||
284 | usleep(100); | ||
285 | } | ||
286 | debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]); | ||
287 | #endif | ||
288 | |||
289 | return &dec->base; | ||
290 | |||
291 | fw_fail: | ||
292 | debug_printf("Cannot create decoder without firmware..\n"); | ||
293 | dec->base.destroy(&dec->base); | ||
294 | return NULL; | ||
295 | |||
296 | fail: | ||
297 | debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret); | ||
298 | dec->base.destroy(&dec->base); | ||
299 | return NULL; | ||
300 | } | ||
301 | |||
302 | struct pipe_video_buffer * | ||
303 | nv98_video_buffer_create(struct pipe_context *pipe, | ||
304 | const struct pipe_video_buffer *templat) | ||
305 | { | ||
306 | return nouveau_vp3_video_buffer_create( | ||
307 | pipe, templat, NV50_RESOURCE_FLAG_VIDEO); | ||
308 | } | ||
diff --git a/src/gallium/drivers/nv50/nv98_video.h b/src/gallium/drivers/nv50/nv98_video.h new file mode 100644 index 00000000000..ea2a3efe19b --- /dev/null +++ b/src/gallium/drivers/nv50/nv98_video.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2013 Maarten Lankhorst, Ilia Mirkin | ||
3 | * | ||
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: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
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. | ||
21 | */ | ||
22 | |||
23 | #include "nv50_context.h" | ||
24 | #include "nv50_screen.h" | ||
25 | #include "nouveau/nouveau_vp3_video.h" | ||
26 | |||
27 | #include "vl/vl_decoder.h" | ||
28 | #include "vl/vl_types.h" | ||
29 | |||
30 | #include "util/u_video.h" | ||
31 | |||
32 | extern unsigned | ||
33 | nv98_decoder_bsp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, | ||
34 | struct nouveau_vp3_video_buffer *target, | ||
35 | unsigned comm_seq, unsigned num_buffers, | ||
36 | const void *const *data, const unsigned *num_bytes, | ||
37 | unsigned *vp_caps, unsigned *is_ref, | ||
38 | struct nouveau_vp3_video_buffer *refs[16]); | ||
39 | |||
40 | extern void | ||
41 | nv98_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, | ||
42 | struct nouveau_vp3_video_buffer *target, unsigned comm_seq, | ||
43 | unsigned caps, unsigned is_ref, | ||
44 | struct nouveau_vp3_video_buffer *refs[16]); | ||
45 | |||
46 | extern void | ||
47 | nv98_decoder_ppp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, | ||
48 | struct nouveau_vp3_video_buffer *target, unsigned comm_seq); | ||
diff --git a/src/gallium/drivers/nv50/nv98_video_bsp.c b/src/gallium/drivers/nv50/nv98_video_bsp.c new file mode 100644 index 00000000000..65128da9e6b --- /dev/null +++ b/src/gallium/drivers/nv50/nv98_video_bsp.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2013 Maarten Lankhorst, Ilia Mirkin | ||
3 | * | ||
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: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
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. | ||
21 | */ | ||
22 | |||
23 | #include "nv98_video.h" | ||
24 | |||
25 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
26 | static void dump_comm_bsp(struct comm *comm) | ||
27 | { | ||
28 | unsigned idx = comm->bsp_cur_index & 0xf; | ||
29 | debug_printf("Cur seq: %x, bsp byte ofs: %x\n", comm->bsp_cur_index, comm->byte_ofs); | ||
30 | debug_printf("Status: %08x, pos: %08x\n", comm->status[idx], comm->pos[idx]); | ||
31 | } | ||
32 | #endif | ||
33 | |||
34 | unsigned | ||
35 | nv98_decoder_bsp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, | ||
36 | struct nouveau_vp3_video_buffer *target, | ||
37 | unsigned comm_seq, unsigned num_buffers, | ||
38 | const void *const *data, const unsigned *num_bytes, | ||
39 | unsigned *vp_caps, unsigned *is_ref, | ||
40 | struct nouveau_vp3_video_buffer *refs[16]) | ||
41 | { | ||
42 | struct nouveau_pushbuf *push = dec->pushbuf[0]; | ||
43 | enum pipe_video_codec codec = u_reduce_video_profile(dec->base.profile); | ||
44 | uint32_t bsp_addr, comm_addr, inter_addr; | ||
45 | uint32_t slice_size, bucket_size, ring_size; | ||
46 | uint32_t caps; | ||
47 | int ret; | ||
48 | struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH]; | ||
49 | struct nouveau_bo *inter_bo = dec->inter_bo[comm_seq & 1]; | ||
50 | unsigned fence_extra = 0; | ||
51 | struct nouveau_pushbuf_refn bo_refs[] = { | ||
52 | { bsp_bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM }, | ||
53 | { inter_bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM }, | ||
54 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
55 | { dec->fence_bo, NOUVEAU_BO_WR | NOUVEAU_BO_GART }, | ||
56 | #endif | ||
57 | { dec->bitplane_bo, NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM }, | ||
58 | }; | ||
59 | int num_refs = sizeof(bo_refs)/sizeof(*bo_refs); | ||
60 | |||
61 | if (!dec->bitplane_bo) | ||
62 | num_refs--; | ||
63 | |||
64 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
65 | fence_extra = 4; | ||
66 | #endif | ||
67 | |||
68 | ret = nouveau_bo_map(bsp_bo, NOUVEAU_BO_WR, dec->client); | ||
69 | if (ret) { | ||
70 | debug_printf("map failed: %i %s\n", ret, strerror(-ret)); | ||
71 | return -1; | ||
72 | } | ||
73 | |||
74 | caps = nouveau_vp3_bsp(dec, desc, target, comm_seq, | ||
75 | num_buffers, data, num_bytes); | ||
76 | |||
77 | nouveau_vp3_vp_caps(dec, desc, target, comm_seq, vp_caps, is_ref, refs); | ||
78 | |||
79 | nouveau_pushbuf_space(push, 6 + (codec == PIPE_VIDEO_CODEC_MPEG4_AVC ? 9 : 8) + fence_extra + 2, num_refs, 0); | ||
80 | nouveau_pushbuf_refn(push, bo_refs, num_refs); | ||
81 | |||
82 | bsp_addr = bsp_bo->offset >> 8; | ||
83 | inter_addr = inter_bo->offset >> 8; | ||
84 | |||
85 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
86 | memset(dec->comm, 0, 0x200); | ||
87 | comm_addr = (dec->fence_bo->offset + COMM_OFFSET) >> 8; | ||
88 | #else | ||
89 | comm_addr = bsp_addr + (COMM_OFFSET>>8); | ||
90 | #endif | ||
91 | |||
92 | BEGIN_NV04(push, SUBC_BSP(0x700), 5); | ||
93 | PUSH_DATA (push, caps); // 700 cmd | ||
94 | PUSH_DATA (push, bsp_addr + 1); // 704 strparm_bsp | ||
95 | PUSH_DATA (push, bsp_addr + 7); // 708 str addr | ||
96 | PUSH_DATA (push, comm_addr); // 70c comm | ||
97 | PUSH_DATA (push, comm_seq); // 710 seq | ||
98 | |||
99 | if (codec != PIPE_VIDEO_CODEC_MPEG4_AVC) { | ||
100 | u32 bitplane_addr; | ||
101 | int mpeg12 = (codec == PIPE_VIDEO_CODEC_MPEG12); | ||
102 | |||
103 | bitplane_addr = dec->bitplane_bo->offset >> 8; | ||
104 | |||
105 | nouveau_vp3_inter_sizes(dec, 1, &slice_size, &bucket_size, &ring_size); | ||
106 | BEGIN_NV04(push, SUBC_BSP(0x400), mpeg12 ? 5 : 7); | ||
107 | PUSH_DATA (push, bsp_addr); // 400 picparm addr | ||
108 | PUSH_DATA (push, inter_addr); // 404 interparm addr | ||
109 | PUSH_DATA (push, inter_addr + slice_size + bucket_size); // 408 interdata addr | ||
110 | PUSH_DATA (push, ring_size << 8); // 40c interdata_size | ||
111 | if (!mpeg12) { | ||
112 | PUSH_DATA (push, bitplane_addr); // 410 BITPLANE_DATA | ||
113 | PUSH_DATA (push, 0x400); // 414 BITPLANE_DATA_SIZE | ||
114 | } | ||
115 | PUSH_DATA (push, 0); // dma idx | ||
116 | } else { | ||
117 | nouveau_vp3_inter_sizes(dec, desc.h264->slice_count, &slice_size, &bucket_size, &ring_size); | ||
118 | BEGIN_NV04(push, SUBC_BSP(0x400), 8); | ||
119 | PUSH_DATA (push, bsp_addr); // 400 picparm addr | ||
120 | PUSH_DATA (push, inter_addr); // 404 interparm addr | ||
121 | PUSH_DATA (push, slice_size << 8); // 408 interparm size? | ||
122 | PUSH_DATA (push, inter_addr + slice_size + bucket_size); // 40c interdata addr | ||
123 | PUSH_DATA (push, ring_size << 8); // 410 interdata size | ||
124 | PUSH_DATA (push, inter_addr + slice_size); // 414 bucket? | ||
125 | PUSH_DATA (push, bucket_size << 8); // 418 bucket size? unshifted.. | ||
126 | PUSH_DATA (push, 0); // 41c targets | ||
127 | // TODO: Double check 414 / 418 with nvidia trace | ||
128 | } | ||
129 | |||
130 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
131 | BEGIN_NV04(push, SUBC_BSP(0x240), 3); | ||
132 | PUSH_DATAh(push, dec->fence_bo->offset); | ||
133 | PUSH_DATA (push, dec->fence_bo->offset); | ||
134 | PUSH_DATA (push, dec->fence_seq); | ||
135 | |||
136 | BEGIN_NV04(push, SUBC_BSP(0x300), 1); | ||
137 | PUSH_DATA (push, 1); | ||
138 | PUSH_KICK (push); | ||
139 | |||
140 | { | ||
141 | unsigned spin = 0; | ||
142 | do { | ||
143 | usleep(100); | ||
144 | if ((spin++ & 0xff) == 0xff) { | ||
145 | debug_printf("b%u: %u\n", dec->fence_seq, dec->fence_map[0]); | ||
146 | dump_comm_bsp(dec->comm); | ||
147 | } | ||
148 | } while (dec->fence_seq > dec->fence_map[0]); | ||
149 | } | ||
150 | |||
151 | dump_comm_bsp(dec->comm); | ||
152 | return dec->comm->status[comm_seq & 0xf]; | ||
153 | #else | ||
154 | BEGIN_NV04(push, SUBC_BSP(0x300), 1); | ||
155 | PUSH_DATA (push, 0); | ||
156 | PUSH_KICK (push); | ||
157 | return 2; | ||
158 | #endif | ||
159 | } | ||
diff --git a/src/gallium/drivers/nv50/nv98_video_ppp.c b/src/gallium/drivers/nv50/nv98_video_ppp.c new file mode 100644 index 00000000000..03659750659 --- /dev/null +++ b/src/gallium/drivers/nv50/nv98_video_ppp.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2013 Maarten Lankhorst, Ilia Mirkin | ||
3 | * | ||
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: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
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. | ||
21 | */ | ||
22 | |||
23 | #include "nv98_video.h" | ||
24 | |||
25 | static void | ||
26 | nv98_decoder_setup_ppp(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video_buffer *target, uint32_t low700) { | ||
27 | struct nouveau_pushbuf *push = dec->pushbuf[2]; | ||
28 | |||
29 | uint32_t stride_in = mb(dec->base.width); | ||
30 | uint32_t stride_out = mb(target->resources[0]->width0); | ||
31 | uint32_t dec_h = mb(dec->base.height); | ||
32 | uint32_t dec_w = mb(dec->base.width); | ||
33 | uint64_t in_addr; | ||
34 | uint32_t y2, cbcr, cbcr2, i; | ||
35 | struct nouveau_pushbuf_refn bo_refs[] = { | ||
36 | { NULL, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM }, | ||
37 | { NULL, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM }, | ||
38 | { dec->ref_bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM }, | ||
39 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
40 | { dec->fence_bo, NOUVEAU_BO_WR | NOUVEAU_BO_GART }, | ||
41 | #endif | ||
42 | }; | ||
43 | unsigned num_refs = sizeof(bo_refs)/sizeof(*bo_refs); | ||
44 | |||
45 | for (i = 0; i < 2; ++i) { | ||
46 | struct nv50_miptree *mt = (struct nv50_miptree *)target->resources[i]; | ||
47 | bo_refs[i].bo = mt->base.bo; | ||
48 | } | ||
49 | |||
50 | nouveau_pushbuf_refn(push, bo_refs, num_refs); | ||
51 | nouveau_vp3_ycbcr_offsets(dec, &y2, &cbcr, &cbcr2); | ||
52 | |||
53 | BEGIN_NV04(push, SUBC_PPP(0x700), 10); | ||
54 | in_addr = nouveau_vp3_video_addr(dec, target) >> 8; | ||
55 | |||
56 | PUSH_DATA (push, (stride_out << 24) | (stride_out << 16) | low700); // 700 | ||
57 | PUSH_DATA (push, (stride_in << 24) | (stride_in << 16) | (dec_h << 8) | dec_w); // 704 | ||
58 | assert(dec_w == stride_in); | ||
59 | |||
60 | /* Input: */ | ||
61 | PUSH_DATA (push, in_addr); // 708 | ||
62 | PUSH_DATA (push, in_addr + y2); // 70c | ||
63 | PUSH_DATA (push, in_addr + cbcr); // 710 | ||
64 | PUSH_DATA (push, in_addr + cbcr2); // 714 | ||
65 | |||
66 | for (i = 0; i < 2; ++i) { | ||
67 | struct nv50_miptree *mt = (struct nv50_miptree *)target->resources[i]; | ||
68 | |||
69 | PUSH_DATA (push, mt->base.address >> 8); | ||
70 | PUSH_DATA (push, (mt->base.address + mt->total_size/2) >> 8); | ||
71 | mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; | ||
72 | } | ||
73 | } | ||
74 | |||
75 | static uint32_t | ||
76 | nv98_decoder_vc1_ppp(struct nouveau_vp3_decoder *dec, struct pipe_vc1_picture_desc *desc, struct nouveau_vp3_video_buffer *target) { | ||
77 | struct nouveau_pushbuf *push = dec->pushbuf[2]; | ||
78 | |||
79 | nv98_decoder_setup_ppp(dec, target, 0x1412); | ||
80 | assert(!desc->deblockEnable); | ||
81 | assert(!(dec->base.width & 0xf)); | ||
82 | assert(!(dec->base.height & 0xf)); | ||
83 | |||
84 | BEGIN_NV04(push, SUBC_PPP(0x400), 1); | ||
85 | PUSH_DATA (push, desc->pquant << 11); | ||
86 | |||
87 | // 728 = wtf? | ||
88 | return 0x10; | ||
89 | } | ||
90 | |||
91 | void | ||
92 | nv98_decoder_ppp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, struct nouveau_vp3_video_buffer *target, unsigned comm_seq) { | ||
93 | enum pipe_video_codec codec = u_reduce_video_profile(dec->base.profile); | ||
94 | struct nouveau_pushbuf *push = dec->pushbuf[2]; | ||
95 | unsigned ppp_caps = 0x10; | ||
96 | unsigned fence_extra = 0; | ||
97 | |||
98 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
99 | fence_extra = 4; | ||
100 | #endif | ||
101 | |||
102 | nouveau_pushbuf_space(push, 11 + (codec == PIPE_VIDEO_CODEC_VC1 ? 2 : 0) + 3 + fence_extra + 2, 4, 0); | ||
103 | |||
104 | switch (codec) { | ||
105 | case PIPE_VIDEO_CODEC_MPEG12: { | ||
106 | unsigned mpeg2 = dec->base.profile != PIPE_VIDEO_PROFILE_MPEG1; | ||
107 | nv98_decoder_setup_ppp(dec, target, 0x1410 | mpeg2); | ||
108 | break; | ||
109 | } | ||
110 | case PIPE_VIDEO_CODEC_MPEG4: nv98_decoder_setup_ppp(dec, target, 0x1414); break; | ||
111 | case PIPE_VIDEO_CODEC_VC1: ppp_caps = nv98_decoder_vc1_ppp(dec, desc.vc1, target); break; | ||
112 | case PIPE_VIDEO_CODEC_MPEG4_AVC: nv98_decoder_setup_ppp(dec, target, 0x1413); break; | ||
113 | default: assert(0); | ||
114 | } | ||
115 | BEGIN_NV04(push, SUBC_PPP(0x734), 2); | ||
116 | PUSH_DATA (push, comm_seq); | ||
117 | PUSH_DATA (push, ppp_caps); | ||
118 | |||
119 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
120 | BEGIN_NV04(push, SUBC_PPP(0x240), 3); | ||
121 | PUSH_DATAh(push, (dec->fence_bo->offset + 0x20)); | ||
122 | PUSH_DATA (push, (dec->fence_bo->offset + 0x20)); | ||
123 | PUSH_DATA (push, dec->fence_seq); | ||
124 | |||
125 | BEGIN_NV04(push, SUBC_PPP(0x300), 1); | ||
126 | PUSH_DATA (push, 1); | ||
127 | PUSH_KICK (push); | ||
128 | |||
129 | { | ||
130 | unsigned spin = 0; | ||
131 | |||
132 | do { | ||
133 | usleep(100); | ||
134 | if ((spin++ & 0xff) == 0xff) | ||
135 | debug_printf("p%u: %u\n", dec->fence_seq, dec->fence_map[8]); | ||
136 | } while (dec->fence_seq > dec->fence_map[8]); | ||
137 | } | ||
138 | #else | ||
139 | BEGIN_NV04(push, SUBC_PPP(0x300), 1); | ||
140 | PUSH_DATA (push, 0); | ||
141 | PUSH_KICK (push); | ||
142 | #endif | ||
143 | } | ||
diff --git a/src/gallium/drivers/nv50/nv98_video_vp.c b/src/gallium/drivers/nv50/nv98_video_vp.c new file mode 100644 index 00000000000..adba58becf3 --- /dev/null +++ b/src/gallium/drivers/nv50/nv98_video_vp.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2013 Maarten Lankhorst, Ilia Mirkin | ||
3 | * | ||
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: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
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. | ||
21 | */ | ||
22 | |||
23 | #include "nv98_video.h" | ||
24 | #include <sys/mman.h> | ||
25 | |||
26 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
27 | static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32 comm_seq, | ||
28 | struct nouveau_bo *inter_bo, unsigned slice_size) | ||
29 | { | ||
30 | unsigned i, idx = comm->pvp_cur_index & 0xf; | ||
31 | debug_printf("Status: %08x, stage: %08x\n", comm->status_vp[idx], comm->pvp_stage); | ||
32 | #if 0 | ||
33 | debug_printf("Acked byte ofs: %x, bsp byte ofs: %x\n", comm->acked_byte_ofs, comm->byte_ofs); | ||
34 | debug_printf("Irq/parse indexes: %i %i\n", comm->irq_index, comm->parse_endpos_index); | ||
35 | |||
36 | for (i = 0; i != comm->irq_index; ++i) | ||
37 | debug_printf("irq[%i] = { @ %08x -> %04x }\n", i, comm->irq_pos[i], comm->irq_470[i]); | ||
38 | for (i = 0; i != comm->parse_endpos_index; ++i) | ||
39 | debug_printf("parse_endpos[%i] = { @ %08x}\n", i, comm->parse_endpos[i]); | ||
40 | #endif | ||
41 | debug_printf("mb_y = %u\n", comm->mb_y[idx]); | ||
42 | if (comm->status_vp[idx] == 1) | ||
43 | return; | ||
44 | |||
45 | if ((comm->pvp_stage & 0xff) != 0xff) { | ||
46 | unsigned *map; | ||
47 | assert(nouveau_bo_map(inter_bo, NOUVEAU_BO_RD|NOUVEAU_BO_NOBLOCK, dec->client) >= 0); | ||
48 | map = inter_bo->map; | ||
49 | for (i = 0; i < comm->byte_ofs + slice_size; i += 0x10) { | ||
50 | debug_printf("%05x: %08x %08x %08x %08x\n", i, map[i/4], map[i/4+1], map[i/4+2], map[i/4+3]); | ||
51 | } | ||
52 | munmap(inter_bo->map, inter_bo->size); | ||
53 | inter_bo->map = NULL; | ||
54 | } | ||
55 | assert((comm->pvp_stage & 0xff) == 0xff); | ||
56 | } | ||
57 | #endif | ||
58 | |||
59 | static void | ||
60 | nv98_decoder_kick_ref(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video_buffer *target) | ||
61 | { | ||
62 | dec->refs[target->valid_ref].vidbuf = NULL; | ||
63 | dec->refs[target->valid_ref].last_used = 0; | ||
64 | // debug_printf("Unreffed %p\n", target); | ||
65 | } | ||
66 | |||
67 | void | ||
68 | nv98_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, | ||
69 | struct nouveau_vp3_video_buffer *target, unsigned comm_seq, | ||
70 | unsigned caps, unsigned is_ref, | ||
71 | struct nouveau_vp3_video_buffer *refs[16]) | ||
72 | { | ||
73 | struct nouveau_pushbuf *push = dec->pushbuf[1]; | ||
74 | uint32_t bsp_addr, comm_addr, inter_addr, ucode_addr, pic_addr[17], last_addr, null_addr; | ||
75 | uint32_t slice_size, bucket_size, ring_size, i; | ||
76 | enum pipe_video_codec codec = u_reduce_video_profile(dec->base.profile); | ||
77 | struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH]; | ||
78 | struct nouveau_bo *inter_bo = dec->inter_bo[comm_seq & 1]; | ||
79 | u32 fence_extra = 0, codec_extra = 0; | ||
80 | struct nouveau_pushbuf_refn bo_refs[] = { | ||
81 | { inter_bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM }, | ||
82 | { dec->ref_bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM }, | ||
83 | { bsp_bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM }, | ||
84 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
85 | { dec->fence_bo, NOUVEAU_BO_WR | NOUVEAU_BO_GART }, | ||
86 | #endif | ||
87 | { dec->fw_bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM }, | ||
88 | }; | ||
89 | int num_refs = sizeof(bo_refs)/sizeof(*bo_refs) - !dec->fw_bo; | ||
90 | |||
91 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
92 | fence_extra = 4; | ||
93 | #endif | ||
94 | |||
95 | if (codec == PIPE_VIDEO_CODEC_MPEG4_AVC) { | ||
96 | nouveau_vp3_inter_sizes(dec, desc.h264->slice_count, &slice_size, &bucket_size, &ring_size); | ||
97 | codec_extra += 2; | ||
98 | } else | ||
99 | nouveau_vp3_inter_sizes(dec, 1, &slice_size, &bucket_size, &ring_size); | ||
100 | |||
101 | if (dec->base.max_references > 2) | ||
102 | codec_extra += 1 + (dec->base.max_references - 2); | ||
103 | |||
104 | pic_addr[16] = nouveau_vp3_video_addr(dec, target) >> 8; | ||
105 | last_addr = null_addr = nouveau_vp3_video_addr(dec, NULL) >> 8; | ||
106 | |||
107 | for (i = 0; i < dec->base.max_references; ++i) { | ||
108 | if (!refs[i]) | ||
109 | pic_addr[i] = last_addr; | ||
110 | else if (dec->refs[refs[i]->valid_ref].vidbuf == refs[i]) | ||
111 | last_addr = pic_addr[i] = nouveau_vp3_video_addr(dec, refs[i]) >> 8; | ||
112 | else | ||
113 | pic_addr[i] = null_addr; | ||
114 | } | ||
115 | if (!is_ref) | ||
116 | nv98_decoder_kick_ref(dec, target); | ||
117 | |||
118 | nouveau_pushbuf_space(push, 8 + 3 * (codec != PIPE_VIDEO_CODEC_MPEG12) + | ||
119 | 6 + codec_extra + fence_extra + 2, num_refs, 0); | ||
120 | |||
121 | nouveau_pushbuf_refn(push, bo_refs, num_refs); | ||
122 | |||
123 | bsp_addr = bsp_bo->offset >> 8; | ||
124 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
125 | comm_addr = (dec->fence_bo->offset + COMM_OFFSET)>>8; | ||
126 | #else | ||
127 | comm_addr = bsp_addr + (COMM_OFFSET>>8); | ||
128 | #endif | ||
129 | inter_addr = inter_bo->offset >> 8; | ||
130 | if (dec->fw_bo) | ||
131 | ucode_addr = dec->fw_bo->offset >> 8; | ||
132 | else | ||
133 | ucode_addr = 0; | ||
134 | |||
135 | BEGIN_NV04(push, SUBC_VP(0x700), 7); | ||
136 | PUSH_DATA (push, caps); // 700 | ||
137 | PUSH_DATA (push, comm_seq); // 704 | ||
138 | PUSH_DATA (push, 0); // 708 fuc targets, ignored for nv98 | ||
139 | PUSH_DATA (push, dec->fw_sizes); // 70c | ||
140 | PUSH_DATA (push, bsp_addr+(VP_OFFSET>>8)); // 710 picparm_addr | ||
141 | PUSH_DATA (push, inter_addr); // 714 inter_parm | ||
142 | PUSH_DATA (push, inter_addr + slice_size + bucket_size); // 718 inter_data_ofs | ||
143 | |||
144 | if (bucket_size) { | ||
145 | uint64_t tmpimg_addr = dec->ref_bo->offset + dec->ref_stride * (dec->base.max_references+2); | ||
146 | |||
147 | BEGIN_NV04(push, SUBC_VP(0x71c), 2); | ||
148 | PUSH_DATA (push, tmpimg_addr >> 8); // 71c | ||
149 | PUSH_DATA (push, inter_addr + slice_size); // 720 bucket_ofs | ||
150 | } | ||
151 | |||
152 | BEGIN_NV04(push, SUBC_VP(0x724), 5); | ||
153 | PUSH_DATA (push, comm_addr); // 724 | ||
154 | PUSH_DATA (push, ucode_addr); // 728 | ||
155 | PUSH_DATA (push, pic_addr[16]); // 734 | ||
156 | PUSH_DATA (push, pic_addr[0]); // 72c | ||
157 | PUSH_DATA (push, pic_addr[1]); // 730 | ||
158 | |||
159 | if (dec->base.max_references > 2) { | ||
160 | int i; | ||
161 | |||
162 | BEGIN_NV04(push, SUBC_VP(0x400), dec->base.max_references - 2); | ||
163 | for (i = 2; i < dec->base.max_references; ++i) { | ||
164 | assert(0x400 + (i - 2) * 4 < 0x438); | ||
165 | PUSH_DATA (push, pic_addr[i]); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | if (codec == PIPE_VIDEO_CODEC_MPEG4_AVC) { | ||
170 | BEGIN_NV04(push, SUBC_VP(0x438), 1); | ||
171 | PUSH_DATA (push, desc.h264->slice_count); | ||
172 | } | ||
173 | |||
174 | //debug_printf("Decoding %08lx with %08lx and %08lx\n", pic_addr[16], pic_addr[0], pic_addr[1]); | ||
175 | |||
176 | #if NOUVEAU_VP3_DEBUG_FENCE | ||
177 | BEGIN_NV04(push, SUBC_VP(0x240), 3); | ||
178 | PUSH_DATAh(push, (dec->fence_bo->offset + 0x10)); | ||
179 | PUSH_DATA (push, (dec->fence_bo->offset + 0x10)); | ||
180 | PUSH_DATA (push, dec->fence_seq); | ||
181 | |||
182 | BEGIN_NV04(push, SUBC_VP(0x300), 1); | ||
183 | PUSH_DATA (push, 1); | ||
184 | PUSH_KICK(push); | ||
185 | |||
186 | { | ||
187 | unsigned spin = 0; | ||
188 | do { | ||
189 | usleep(100); | ||
190 | if ((spin++ & 0xff) == 0xff) { | ||
191 | debug_printf("v%u: %u\n", dec->fence_seq, dec->fence_map[4]); | ||
192 | dump_comm_vp(dec, dec->comm, comm_seq, inter_bo, slice_size << 8); | ||
193 | } | ||
194 | } while (dec->fence_seq > dec->fence_map[4]); | ||
195 | } | ||
196 | dump_comm_vp(dec, dec->comm, comm_seq, inter_bo, slice_size << 8); | ||
197 | #else | ||
198 | BEGIN_NV04(push, SUBC_VP(0x300), 1); | ||
199 | PUSH_DATA (push, 0); | ||
200 | PUSH_KICK (push); | ||
201 | #endif | ||
202 | } | ||