gallium: replace INLINE with inline
[mesa.git] / src / gallium / drivers / nouveau / nv50 / nv98_video.c
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/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_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 = 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_codec *
60 nv98_create_decoder(struct pipe_context *context,
61 const struct pipe_video_codec *templ)
62 {
63 struct nouveau_screen *screen = &((struct nv50_context *)context)->screen->base;
64 struct nouveau_vp3_decoder *dec;
65 struct nouveau_pushbuf **push;
66 struct nv04_fifo nv04_data = {.vram = 0xbeef0201, .gart = 0xbeef0202};
67
68 int ret, i;
69 uint32_t codec = 1, ppp_codec = 3;
70 uint32_t timeout;
71 u32 tmp_size = 0;
72
73 if (getenv("XVMC_VL"))
74 return vl_create_decoder(context, templ);
75
76 if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
77 debug_printf("%x\n", templ->entrypoint);
78 return NULL;
79 }
80
81 dec = CALLOC_STRUCT(nouveau_vp3_decoder);
82 if (!dec)
83 return NULL;
84 dec->client = screen->client;
85 dec->base = *templ;
86 nouveau_vp3_decoder_init_common(&dec->base);
87
88 dec->bsp_idx = 5;
89 dec->vp_idx = 6;
90 dec->ppp_idx = 7;
91
92 ret = nouveau_object_new(&screen->device->object, 0,
93 NOUVEAU_FIFO_CHANNEL_CLASS,
94 &nv04_data, sizeof(nv04_data), &dec->channel[0]);
95
96 if (!ret)
97 ret = nouveau_pushbuf_new(screen->client, dec->channel[0], 4,
98 32 * 1024, true, &dec->pushbuf[0]);
99
100 for (i = 1; i < 3; ++i) {
101 dec->channel[i] = dec->channel[0];
102 dec->pushbuf[i] = dec->pushbuf[0];
103 }
104 push = dec->pushbuf;
105
106 if (!ret)
107 ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x85b1, NULL, 0, &dec->bsp);
108 if (!ret)
109 ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x85b2, NULL, 0, &dec->vp);
110 if (!ret)
111 ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x85b3, NULL, 0, &dec->ppp);
112 if (ret)
113 goto fail;
114
115 BEGIN_NV04(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
116 PUSH_DATA (push[0], dec->bsp->handle);
117
118 BEGIN_NV04(push[0], SUBC_BSP(0x180), 5);
119 for (i = 0; i < 5; i++)
120 PUSH_DATA (push[0], nv04_data.vram);
121
122 BEGIN_NV04(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
123 PUSH_DATA (push[1], dec->vp->handle);
124
125 BEGIN_NV04(push[1], SUBC_VP(0x180), 6);
126 for (i = 0; i < 6; i++)
127 PUSH_DATA (push[1], nv04_data.vram);
128
129 BEGIN_NV04(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
130 PUSH_DATA (push[2], dec->ppp->handle);
131
132 BEGIN_NV04(push[2], SUBC_PPP(0x180), 5);
133 for (i = 0; i < 5; i++)
134 PUSH_DATA (push[2], nv04_data.vram);
135
136 dec->base.context = context;
137 dec->base.decode_bitstream = nv98_decoder_decode_bitstream;
138
139 for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
140 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
141 0, 1 << 20, NULL, &dec->bsp_bo[i]);
142 if (!ret)
143 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
144 0x100, 4 << 20, NULL, &dec->inter_bo[0]);
145 if (!ret)
146 nouveau_bo_ref(dec->inter_bo[0], &dec->inter_bo[1]);
147 if (ret)
148 goto fail;
149
150 switch (u_reduce_video_profile(templ->profile)) {
151 case PIPE_VIDEO_FORMAT_MPEG12: {
152 codec = 1;
153 assert(templ->max_references <= 2);
154 break;
155 }
156 case PIPE_VIDEO_FORMAT_MPEG4: {
157 codec = 4;
158 tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
159 assert(templ->max_references <= 2);
160 break;
161 }
162 case PIPE_VIDEO_FORMAT_VC1: {
163 ppp_codec = codec = 2;
164 tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
165 assert(templ->max_references <= 2);
166 break;
167 }
168 case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
169 codec = 3;
170 dec->tmp_stride = 16 * mb_half(templ->width) * nouveau_vp3_video_align(templ->height) * 3 / 2;
171 tmp_size = dec->tmp_stride * (templ->max_references + 1);
172 assert(templ->max_references <= 16);
173 break;
174 }
175 default:
176 fprintf(stderr, "invalid codec\n");
177 goto fail;
178 }
179
180 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
181 0x4000, NULL, &dec->fw_bo);
182 if (ret)
183 goto fail;
184
185 ret = nouveau_vp3_load_firmware(dec, templ->profile, screen->device->chipset);
186 if (ret)
187 goto fw_fail;
188
189 if (codec != 3) {
190 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
191 0x400, NULL, &dec->bitplane_bo);
192 if (ret)
193 goto fail;
194 }
195
196 dec->ref_stride = mb(templ->width)*16 * (mb_half(templ->height)*32 + nouveau_vp3_video_align(templ->height)/2);
197 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
198 dec->ref_stride * (templ->max_references+2) + tmp_size,
199 NULL, &dec->ref_bo);
200 if (ret)
201 goto fail;
202
203 timeout = 0;
204
205 BEGIN_NV04(push[0], SUBC_BSP(0x200), 2);
206 PUSH_DATA (push[0], codec);
207 PUSH_DATA (push[0], timeout);
208
209 BEGIN_NV04(push[1], SUBC_VP(0x200), 2);
210 PUSH_DATA (push[1], codec);
211 PUSH_DATA (push[1], timeout);
212
213 BEGIN_NV04(push[2], SUBC_PPP(0x200), 2);
214 PUSH_DATA (push[2], ppp_codec);
215 PUSH_DATA (push[2], timeout);
216
217 ++dec->fence_seq;
218
219 #if NOUVEAU_VP3_DEBUG_FENCE
220 ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
221 0, 0x1000, NULL, &dec->fence_bo);
222 if (ret)
223 goto fail;
224
225 nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
226 dec->fence_map = dec->fence_bo->map;
227 dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
228 dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
229
230 /* So lets test if the fence is working? */
231 nouveau_pushbuf_space(push[0], 6, 1, 0);
232 PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
233 BEGIN_NV04(push[0], SUBC_BSP(0x240), 3);
234 PUSH_DATAh(push[0], dec->fence_bo->offset);
235 PUSH_DATA (push[0], dec->fence_bo->offset);
236 PUSH_DATA (push[0], dec->fence_seq);
237
238 BEGIN_NV04(push[0], SUBC_BSP(0x304), 1);
239 PUSH_DATA (push[0], 0);
240 PUSH_KICK (push[0]);
241
242 nouveau_pushbuf_space(push[1], 6, 1, 0);
243 PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
244 BEGIN_NV04(push[1], SUBC_VP(0x240), 3);
245 PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
246 PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
247 PUSH_DATA (push[1], dec->fence_seq);
248
249 BEGIN_NV04(push[1], SUBC_VP(0x304), 1);
250 PUSH_DATA (push[1], 0);
251 PUSH_KICK (push[1]);
252
253 nouveau_pushbuf_space(push[2], 6, 1, 0);
254 PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
255 BEGIN_NV04(push[2], SUBC_PPP(0x240), 3);
256 PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
257 PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
258 PUSH_DATA (push[2], dec->fence_seq);
259
260 BEGIN_NV04(push[2], SUBC_PPP(0x304), 1);
261 PUSH_DATA (push[2], 0);
262 PUSH_KICK (push[2]);
263
264 usleep(100);
265 while (dec->fence_seq > dec->fence_map[0] ||
266 dec->fence_seq > dec->fence_map[4] ||
267 dec->fence_seq > dec->fence_map[8]) {
268 debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
269 usleep(100);
270 }
271 debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
272 #endif
273
274 return &dec->base;
275
276 fw_fail:
277 debug_printf("Cannot create decoder without firmware..\n");
278 dec->base.destroy(&dec->base);
279 return NULL;
280
281 fail:
282 debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
283 dec->base.destroy(&dec->base);
284 return NULL;
285 }
286
287 struct pipe_video_buffer *
288 nv98_video_buffer_create(struct pipe_context *pipe,
289 const struct pipe_video_buffer *templat)
290 {
291 return nouveau_vp3_video_buffer_create(
292 pipe, templat, NV50_RESOURCE_FLAG_VIDEO);
293 }