1 /*
2 * Copyright 2011-2013 Maarten Lankhorst
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 "nvc0/nvc0_video.h"
24
25 #include "util/u_sampler.h"
26 #include "util/u_format.h"
27
28 static void
nvc0_decoder_begin_frame(struct pipe_video_codec * decoder,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)29 nvc0_decoder_begin_frame(struct pipe_video_codec *decoder,
30 struct pipe_video_buffer *target,
31 struct pipe_picture_desc *picture)
32 {
33 struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
34 uint32_t comm_seq = ++dec->fence_seq;
35 unsigned ret = 0;
36
37 assert(dec);
38 assert(target);
39 assert(target->buffer_format == PIPE_FORMAT_NV12);
40
41 ret = nvc0_decoder_bsp_begin(dec, comm_seq);
42
43 assert(ret == 2);
44 }
45
46 static void
nvc0_decoder_decode_bitstream(struct pipe_video_codec * decoder,struct pipe_video_buffer * video_target,struct pipe_picture_desc * picture,unsigned num_buffers,const void * const * data,const unsigned * num_bytes)47 nvc0_decoder_decode_bitstream(struct pipe_video_codec *decoder,
48 struct pipe_video_buffer *video_target,
49 struct pipe_picture_desc *picture,
50 unsigned num_buffers,
51 const void *const *data,
52 const unsigned *num_bytes)
53 {
54 struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
55 uint32_t comm_seq = dec->fence_seq;
56 unsigned ret = 0;
57
58 assert(decoder);
59
60 ret = nvc0_decoder_bsp_next(dec, comm_seq, num_buffers, data, num_bytes);
61
62 assert(ret == 2);
63 }
64
65 static void
nvc0_decoder_end_frame(struct pipe_video_codec * decoder,struct pipe_video_buffer * video_target,struct pipe_picture_desc * picture)66 nvc0_decoder_end_frame(struct pipe_video_codec *decoder,
67 struct pipe_video_buffer *video_target,
68 struct pipe_picture_desc *picture)
69 {
70 struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
71 struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target;
72 uint32_t comm_seq = dec->fence_seq;
73 union pipe_desc desc;
74
75 unsigned vp_caps, is_ref, ret;
76 struct nouveau_vp3_video_buffer *refs[16] = {};
77
78 desc.base = picture;
79
80 ret = nvc0_decoder_bsp_end(dec, desc, target, comm_seq, &vp_caps, &is_ref, refs);
81
82 /* did we decode bitstream correctly? */
83 assert(ret == 2);
84
85 nvc0_decoder_vp(dec, desc, target, comm_seq, vp_caps, is_ref, refs);
86 nvc0_decoder_ppp(dec, desc, target, comm_seq);
87 }
88
89 struct pipe_video_codec *
nvc0_create_decoder(struct pipe_context * context,const struct pipe_video_codec * templ)90 nvc0_create_decoder(struct pipe_context *context,
91 const struct pipe_video_codec *templ)
92 {
93 struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base;
94 struct nouveau_vp3_decoder *dec;
95 struct nouveau_pushbuf **push;
96 union nouveau_bo_config cfg;
97 bool kepler = screen->device->chipset >= 0xe0;
98
99 cfg.nvc0.tile_mode = 0x10;
100 cfg.nvc0.memtype = 0xfe;
101
102 int ret, i;
103 uint32_t codec = 1, ppp_codec = 3;
104 uint32_t timeout;
105 u32 tmp_size = 0;
106
107 if (getenv("XVMC_VL"))
108 return vl_create_decoder(context, templ);
109
110 if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
111 debug_printf("%x\n", templ->entrypoint);
112 return NULL;
113 }
114
115 dec = CALLOC_STRUCT(nouveau_vp3_decoder);
116 if (!dec)
117 return NULL;
118 dec->client = screen->client;
119 dec->base = *templ;
120 nouveau_vp3_decoder_init_common(&dec->base);
121
122 if (!kepler) {
123 dec->bsp_idx = 5;
124 dec->vp_idx = 6;
125 dec->ppp_idx = 7;
126 } else {
127 dec->bsp_idx = 2;
128 dec->vp_idx = 2;
129 dec->ppp_idx = 2;
130 }
131
132 for (i = 0; i < 3; ++i)
133 if (i && !kepler) {
134 dec->channel[i] = dec->channel[0];
135 dec->pushbuf[i] = dec->pushbuf[0];
136 } else {
137 void *data;
138 u32 size;
139 struct nvc0_fifo nvc0_args = {};
140 struct nve0_fifo nve0_args = {};
141
142 if (!kepler) {
143 size = sizeof(nvc0_args);
144 data = &nvc0_args;
145 } else {
146 unsigned engine[] = {
147 NVE0_FIFO_ENGINE_BSP,
148 NVE0_FIFO_ENGINE_VP,
149 NVE0_FIFO_ENGINE_PPP
150 };
151
152 nve0_args.engine = engine[i];
153 size = sizeof(nve0_args);
154 data = &nve0_args;
155 }
156
157 ret = nouveau_object_new(&screen->device->object, 0,
158 NOUVEAU_FIFO_CHANNEL_CLASS,
159 data, size, &dec->channel[i]);
160
161 if (!ret)
162 ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4,
163 32 * 1024, true, &dec->pushbuf[i]);
164 if (ret)
165 break;
166 }
167 push = dec->pushbuf;
168
169 if (!kepler) {
170 if (!ret)
171 ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp);
172 if (!ret)
173 ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp);
174 if (!ret)
175 ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp);
176 } else {
177 if (!ret)
178 ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp);
179 if (!ret)
180 ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp);
181 if (!ret)
182 ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp);
183 }
184 if (ret)
185 goto fail;
186
187 BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
188 PUSH_DATA (push[0], dec->bsp->handle);
189
190 BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
191 PUSH_DATA (push[1], dec->vp->handle);
192
193 BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
194 PUSH_DATA (push[2], dec->ppp->handle);
195
196 dec->base.context = context;
197 dec->base.begin_frame = nvc0_decoder_begin_frame;
198 dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
199 dec->base.end_frame = nvc0_decoder_end_frame;
200
201 for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
202 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
203 0, 1 << 20, &cfg, &dec->bsp_bo[i]);
204 if (!ret) {
205 /* total fudge factor... just has to be bigger for higher bitrates? */
206 unsigned inter_size = align(templ->width * templ->height * 2, 4 << 20);
207 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
208 0x100, inter_size, &cfg, &dec->inter_bo[0]);
209 }
210 if (!ret) {
211 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
212 0x100, dec->inter_bo[0]->size, &cfg,
213 &dec->inter_bo[1]);
214 }
215 if (ret)
216 goto fail;
217 switch (u_reduce_video_profile(templ->profile)) {
218 case PIPE_VIDEO_FORMAT_MPEG12: {
219 codec = 1;
220 assert(templ->max_references <= 2);
221 break;
222 }
223 case PIPE_VIDEO_FORMAT_MPEG4: {
224 codec = 4;
225 tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
226 assert(templ->max_references <= 2);
227 break;
228 }
229 case PIPE_VIDEO_FORMAT_VC1: {
230 ppp_codec = codec = 2;
231 tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
232 assert(templ->max_references <= 2);
233 break;
234 }
235 case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
236 codec = 3;
237 dec->tmp_stride = 16 * mb_half(templ->width) * nouveau_vp3_video_align(templ->height) * 3 / 2;
238 tmp_size = dec->tmp_stride * (templ->max_references + 1);
239 assert(templ->max_references <= 16);
240 break;
241 }
242 default:
243 fprintf(stderr, "invalid codec\n");
244 goto fail;
245 }
246
247 if (screen->device->chipset < 0xd0) {
248 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
249 0x4000, &cfg, &dec->fw_bo);
250 if (ret)
251 goto fail;
252
253 ret = nouveau_vp3_load_firmware(dec, templ->profile, screen->device->chipset);
254 if (ret)
255 goto fw_fail;
256 }
257
258 if (codec != 3) {
259 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
260 0x400, &cfg, &dec->bitplane_bo);
261 if (ret)
262 goto fail;
263 }
264
265 dec->ref_stride = mb(templ->width)*16 * (mb_half(templ->height)*32 + nouveau_vp3_video_align(templ->height)/2);
266 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
267 dec->ref_stride * (templ->max_references+2) + tmp_size,
268 &cfg, &dec->ref_bo);
269 if (ret)
270 goto fail;
271
272 timeout = 0;
273
274 BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2);
275 PUSH_DATA (push[0], codec);
276 PUSH_DATA (push[0], timeout);
277
278 BEGIN_NVC0(push[1], SUBC_VP(0x200), 2);
279 PUSH_DATA (push[1], codec);
280 PUSH_DATA (push[1], timeout);
281
282 BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2);
283 PUSH_DATA (push[2], ppp_codec);
284 PUSH_DATA (push[2], timeout);
285
286 ++dec->fence_seq;
287
288 #if NOUVEAU_VP3_DEBUG_FENCE
289 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
290 0, 0x1000, NULL, &dec->fence_bo);
291 if (ret)
292 goto fail;
293
294 nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
295 dec->fence_map = dec->fence_bo->map;
296 dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
297 dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
298
299 /* So lets test if the fence is working? */
300 nouveau_pushbuf_space(push[0], 16, 1, 0);
301 PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
302 BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
303 PUSH_DATAh(push[0], dec->fence_bo->offset);
304 PUSH_DATA (push[0], dec->fence_bo->offset);
305 PUSH_DATA (push[0], dec->fence_seq);
306
307 BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
308 PUSH_DATA (push[0], 0);
309 PUSH_KICK (push[0]);
310
311 nouveau_pushbuf_space(push[1], 16, 1, 0);
312 PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
313 BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
314 PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
315 PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
316 PUSH_DATA (push[1], dec->fence_seq);
317
318 BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
319 PUSH_DATA (push[1], 0);
320 PUSH_KICK (push[1]);
321
322 nouveau_pushbuf_space(push[2], 16, 1, 0);
323 PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
324 BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
325 PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
326 PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
327 PUSH_DATA (push[2], dec->fence_seq);
328
329 BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
330 PUSH_DATA (push[2], 0);
331 PUSH_KICK (push[2]);
332
333 usleep(100);
334 while (dec->fence_seq > dec->fence_map[0] ||
335 dec->fence_seq > dec->fence_map[4] ||
336 dec->fence_seq > dec->fence_map[8]) {
337 debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
338 usleep(100);
339 }
340 debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
341 #endif
342
343 return &dec->base;
344
345 fw_fail:
346 debug_printf("Cannot create decoder without firmware..\n");
347 dec->base.destroy(&dec->base);
348 return NULL;
349
350 fail:
351 debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
352 dec->base.destroy(&dec->base);
353 return NULL;
354 }
355
356 struct pipe_video_buffer *
nvc0_video_buffer_create(struct pipe_context * pipe,const struct pipe_video_buffer * templat)357 nvc0_video_buffer_create(struct pipe_context *pipe,
358 const struct pipe_video_buffer *templat)
359 {
360 return nouveau_vp3_video_buffer_create(
361 pipe, templat, NVC0_RESOURCE_FLAG_VIDEO);
362 }
363