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