summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlia Mirkin <imirkin@alum.mit.edu>2013-08-10 20:19:24 -0400
committerMaarten Lankhorst <maarten.lankhorst@canonical.com>2013-08-16 09:48:47 +0200
commita2061eea0f89b44c816e6c7570b983e8cfda41cd (patch)
treedf7ea1084a69bc4c20b8ef2c11df611613756283
parentb3f6f127f28737d034dcf1c12a9b66b88750e93b (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.c39
-rw-r--r--src/gallium/drivers/nv50/Makefile.sources6
-rw-r--r--src/gallium/drivers/nv50/nv50_context.c5
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h14
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.c7
-rw-r--r--src/gallium/drivers/nv50/nv50_winsys.h4
-rw-r--r--src/gallium/drivers/nv50/nv84_video.h4
-rw-r--r--src/gallium/drivers/nv50/nv98_video.c308
-rw-r--r--src/gallium/drivers/nv50/nv98_video.h48
-rw-r--r--src/gallium/drivers/nv50/nv98_video_bsp.c159
-rw-r--r--src/gallium/drivers/nv50/nv98_video_ppp.c143
-rw-r--r--src/gallium/drivers/nv50/nv98_video_vp.c202
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
234static 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
234static void vp4_getpath(enum pipe_video_profile profile, char *path) 253static 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
21CODEGEN_NV50_SOURCES := \ 25CODEGEN_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 */
317struct pipe_video_decoder *
318nv98_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
326struct pipe_video_buffer *
327nv98_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
68static INLINE uint32_t 64static INLINE uint32_t
69NV50_FIFO_PKHDR(int subc, int mthd, unsigned size) 65NV50_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
36union pipe_desc { 40union 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
28static void
29nv98_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
59struct pipe_video_decoder *
60nv98_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
291fw_fail:
292 debug_printf("Cannot create decoder without firmware..\n");
293 dec->base.destroy(&dec->base);
294 return NULL;
295
296fail:
297 debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
298 dec->base.destroy(&dec->base);
299 return NULL;
300}
301
302struct pipe_video_buffer *
303nv98_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
32extern unsigned
33nv98_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
40extern void
41nv98_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
46extern void
47nv98_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
26static 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
34unsigned
35nv98_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
25static void
26nv98_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
75static uint32_t
76nv98_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
91void
92nv98_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
27static 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
59static void
60nv98_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
67void
68nv98_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}