freedreno: consolidate C sources list into Makefile.sources
[mesa.git] / src / gallium / drivers / nouveau / nouveau_vp3_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 <sys/mman.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26
27 #include "nouveau_screen.h"
28 #include "nouveau_context.h"
29 #include "nouveau_vp3_video.h"
30
31 #include "util/u_video.h"
32 #include "util/u_format.h"
33 #include "util/u_sampler.h"
34
35 static struct pipe_sampler_view **
36 nouveau_vp3_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
37 {
38 struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
39 return buf->sampler_view_planes;
40 }
41
42 static struct pipe_sampler_view **
43 nouveau_vp3_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
44 {
45 struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
46 return buf->sampler_view_components;
47 }
48
49 static struct pipe_surface **
50 nouveau_vp3_video_buffer_surfaces(struct pipe_video_buffer *buffer)
51 {
52 struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
53 return buf->surfaces;
54 }
55
56 static void
57 nouveau_vp3_video_buffer_destroy(struct pipe_video_buffer *buffer)
58 {
59 struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
60 unsigned i;
61
62 assert(buf);
63
64 for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
65 pipe_resource_reference(&buf->resources[i], NULL);
66 pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
67 pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
68 pipe_surface_reference(&buf->surfaces[i * 2], NULL);
69 pipe_surface_reference(&buf->surfaces[i * 2 + 1], NULL);
70 }
71 FREE(buffer);
72 }
73
74 struct pipe_video_buffer *
75 nouveau_vp3_video_buffer_create(struct pipe_context *pipe,
76 const struct pipe_video_buffer *templat,
77 int flags)
78 {
79 struct nouveau_vp3_video_buffer *buffer;
80 struct pipe_resource templ;
81 unsigned i, j, component;
82 struct pipe_sampler_view sv_templ;
83 struct pipe_surface surf_templ;
84
85 assert(templat->interlaced);
86 if (getenv("XVMC_VL") || templat->buffer_format != PIPE_FORMAT_NV12)
87 return vl_video_buffer_create(pipe, templat);
88
89 assert(templat->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
90
91 buffer = CALLOC_STRUCT(nouveau_vp3_video_buffer);
92 if (!buffer)
93 return NULL;
94
95 buffer->base.buffer_format = templat->buffer_format;
96 buffer->base.context = pipe;
97 buffer->base.destroy = nouveau_vp3_video_buffer_destroy;
98 buffer->base.chroma_format = templat->chroma_format;
99 buffer->base.width = templat->width;
100 buffer->base.height = templat->height;
101 buffer->base.get_sampler_view_planes = nouveau_vp3_video_buffer_sampler_view_planes;
102 buffer->base.get_sampler_view_components = nouveau_vp3_video_buffer_sampler_view_components;
103 buffer->base.get_surfaces = nouveau_vp3_video_buffer_surfaces;
104 buffer->base.interlaced = true;
105
106 memset(&templ, 0, sizeof(templ));
107 templ.target = PIPE_TEXTURE_2D_ARRAY;
108 templ.depth0 = 1;
109 templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
110 templ.format = PIPE_FORMAT_R8_UNORM;
111 templ.width0 = buffer->base.width;
112 templ.height0 = (buffer->base.height + 1)/2;
113 templ.flags = flags;
114 templ.array_size = 2;
115
116 buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ);
117 if (!buffer->resources[0])
118 goto error;
119
120 templ.format = PIPE_FORMAT_R8G8_UNORM;
121 buffer->num_planes = 2;
122 templ.width0 = (templ.width0 + 1) / 2;
123 templ.height0 = (templ.height0 + 1) / 2;
124 for (i = 1; i < buffer->num_planes; ++i) {
125 buffer->resources[i] = pipe->screen->resource_create(pipe->screen, &templ);
126 if (!buffer->resources[i])
127 goto error;
128 }
129
130 memset(&sv_templ, 0, sizeof(sv_templ));
131 for (component = 0, i = 0; i < buffer->num_planes; ++i ) {
132 struct pipe_resource *res = buffer->resources[i];
133 unsigned nr_components = util_format_get_nr_components(res->format);
134
135 u_sampler_view_default_template(&sv_templ, res, res->format);
136 buffer->sampler_view_planes[i] = pipe->create_sampler_view(pipe, res, &sv_templ);
137 if (!buffer->sampler_view_planes[i])
138 goto error;
139
140 for (j = 0; j < nr_components; ++j, ++component) {
141 sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j;
142 sv_templ.swizzle_a = PIPE_SWIZZLE_ONE;
143
144 buffer->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
145 if (!buffer->sampler_view_components[component])
146 goto error;
147 }
148 }
149
150 memset(&surf_templ, 0, sizeof(surf_templ));
151 for (j = 0; j < buffer->num_planes; ++j) {
152 surf_templ.format = buffer->resources[j]->format;
153 surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 0;
154 buffer->surfaces[j * 2] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
155 if (!buffer->surfaces[j * 2])
156 goto error;
157
158 surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 1;
159 buffer->surfaces[j * 2 + 1] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
160 if (!buffer->surfaces[j * 2 + 1])
161 goto error;
162 }
163
164 return &buffer->base;
165
166 error:
167 nouveau_vp3_video_buffer_destroy(&buffer->base);
168 return NULL;
169 }
170
171 static void
172 nouveau_vp3_decoder_flush(struct pipe_video_codec *decoder)
173 {
174 }
175
176 static void
177 nouveau_vp3_decoder_begin_frame(struct pipe_video_codec *decoder,
178 struct pipe_video_buffer *target,
179 struct pipe_picture_desc *picture)
180 {
181 }
182
183 static void
184 nouveau_vp3_decoder_end_frame(struct pipe_video_codec *decoder,
185 struct pipe_video_buffer *target,
186 struct pipe_picture_desc *picture)
187 {
188 }
189
190 static void
191 nouveau_vp3_decoder_destroy(struct pipe_video_codec *decoder)
192 {
193 struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
194 int i;
195
196 nouveau_bo_ref(NULL, &dec->ref_bo);
197 nouveau_bo_ref(NULL, &dec->bitplane_bo);
198 nouveau_bo_ref(NULL, &dec->inter_bo[0]);
199 nouveau_bo_ref(NULL, &dec->inter_bo[1]);
200 #if NOUVEAU_VP3_DEBUG_FENCE
201 nouveau_bo_ref(NULL, &dec->fence_bo);
202 #endif
203 nouveau_bo_ref(NULL, &dec->fw_bo);
204
205 for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH; ++i)
206 nouveau_bo_ref(NULL, &dec->bsp_bo[i]);
207
208 nouveau_object_del(&dec->bsp);
209 nouveau_object_del(&dec->vp);
210 nouveau_object_del(&dec->ppp);
211
212 if (dec->channel[0] != dec->channel[1]) {
213 for (i = 0; i < 3; ++i) {
214 nouveau_pushbuf_del(&dec->pushbuf[i]);
215 nouveau_object_del(&dec->channel[i]);
216 }
217 } else {
218 nouveau_pushbuf_del(dec->pushbuf);
219 nouveau_object_del(dec->channel);
220 }
221
222 FREE(dec);
223 }
224
225 void
226 nouveau_vp3_decoder_init_common(struct pipe_video_codec *dec)
227 {
228 dec->destroy = nouveau_vp3_decoder_destroy;
229 dec->flush = nouveau_vp3_decoder_flush;
230 dec->begin_frame = nouveau_vp3_decoder_begin_frame;
231 dec->end_frame = nouveau_vp3_decoder_end_frame;
232 }
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_FORMAT_MPEG12: {
238 sprintf(path, "/lib/firmware/nouveau/vuc-vp3-mpeg12-0");
239 break;
240 }
241 case PIPE_VIDEO_FORMAT_VC1: {
242 sprintf(path, "/lib/firmware/nouveau/vuc-vp3-vc1-0");
243 break;
244 }
245 case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
246 sprintf(path, "/lib/firmware/nouveau/vuc-vp3-h264-0");
247 break;
248 }
249 default: assert(0);
250 }
251 }
252
253 static void vp4_getpath(enum pipe_video_profile profile, char *path)
254 {
255 switch (u_reduce_video_profile(profile)) {
256 case PIPE_VIDEO_FORMAT_MPEG12: {
257 sprintf(path, "/lib/firmware/nouveau/vuc-mpeg12-0");
258 break;
259 }
260 case PIPE_VIDEO_FORMAT_MPEG4: {
261 sprintf(path, "/lib/firmware/nouveau/vuc-mpeg4-0");
262 break;
263 }
264 case PIPE_VIDEO_FORMAT_VC1: {
265 sprintf(path, "/lib/firmware/nouveau/vuc-vc1-0");
266 break;
267 }
268 case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
269 sprintf(path, "/lib/firmware/nouveau/vuc-h264-0");
270 break;
271 }
272 default: assert(0);
273 }
274 }
275
276 int
277 nouveau_vp3_load_firmware(struct nouveau_vp3_decoder *dec,
278 enum pipe_video_profile profile,
279 unsigned chipset)
280 {
281 int fd;
282 char path[PATH_MAX];
283 ssize_t r;
284 uint32_t *end, endval;
285
286 if (chipset >= 0xa3 && chipset != 0xaa && chipset != 0xac)
287 vp4_getpath(profile, path);
288 else
289 vp3_getpath(profile, path);
290
291 if (nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client))
292 return 1;
293
294 fd = open(path, O_RDONLY | O_CLOEXEC);
295 if (fd < 0) {
296 fprintf(stderr, "opening firmware file %s failed: %m\n", path);
297 return 1;
298 }
299 r = read(fd, dec->fw_bo->map, 0x4000);
300 close(fd);
301
302 if (r < 0) {
303 fprintf(stderr, "reading firmware file %s failed: %m\n", path);
304 return 1;
305 }
306
307 if (r == 0x4000) {
308 fprintf(stderr, "firmware file %s too large!\n", path);
309 return 1;
310 }
311
312 if (r & 0xff) {
313 fprintf(stderr, "firmware file %s wrong size!\n", path);
314 return 1;
315 }
316
317 end = dec->fw_bo->map + r - 4;
318 endval = *end;
319 while (endval == *end)
320 end--;
321
322 r = (intptr_t)end - (intptr_t)dec->fw_bo->map + 4;
323
324 switch (u_reduce_video_profile(profile)) {
325 case PIPE_VIDEO_FORMAT_MPEG12: {
326 assert((r & 0xff) == 0xe0);
327 dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
328 break;
329 }
330 case PIPE_VIDEO_FORMAT_MPEG4: {
331 assert((r & 0xff) == 0xe0);
332 dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
333 break;
334 }
335 case PIPE_VIDEO_FORMAT_VC1: {
336 assert((r & 0xff) == 0xac);
337 dec->fw_sizes = (0x3ac<<16) | (r - 0x3ac);
338 break;
339 }
340 case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
341 assert((r & 0xff) == 0x70);
342 dec->fw_sizes = (0x370<<16) | (r - 0x370);
343 break;
344 }
345 default:
346 return 1;
347 }
348 munmap(dec->fw_bo->map, dec->fw_bo->size);
349 dec->fw_bo->map = NULL;
350 return 0;
351 }
352
353 int
354 nouveau_vp3_screen_get_video_param(struct pipe_screen *pscreen,
355 enum pipe_video_profile profile,
356 enum pipe_video_entrypoint entrypoint,
357 enum pipe_video_cap param)
358 {
359 int chipset = nouveau_screen(pscreen)->device->chipset;
360 int vp3 = chipset < 0xa3 || chipset == 0xaa || chipset == 0xac;
361 int vp5 = chipset >= 0xd0;
362 enum pipe_video_format codec = u_reduce_video_profile(profile);
363 switch (param) {
364 case PIPE_VIDEO_CAP_SUPPORTED:
365 /* For now, h264 and mpeg4 don't work on pre-nvc0. */
366 if (chipset < 0xc0)
367 return codec == PIPE_VIDEO_FORMAT_MPEG12 ||
368 codec == PIPE_VIDEO_FORMAT_VC1;
369 /* In the general case, this should work, once the pre-nvc0 problems are
370 * resolved. */
371 return profile >= PIPE_VIDEO_PROFILE_MPEG1 && (
372 !vp3 || codec != PIPE_VIDEO_FORMAT_MPEG4);
373 case PIPE_VIDEO_CAP_NPOT_TEXTURES:
374 return 1;
375 case PIPE_VIDEO_CAP_MAX_WIDTH:
376 case PIPE_VIDEO_CAP_MAX_HEIGHT:
377 return vp5 ? 4096 : 2048;
378 case PIPE_VIDEO_CAP_PREFERED_FORMAT:
379 return PIPE_FORMAT_NV12;
380 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
381 case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
382 return true;
383 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
384 return false;
385 case PIPE_VIDEO_CAP_MAX_LEVEL:
386 switch (profile) {
387 case PIPE_VIDEO_PROFILE_MPEG1:
388 return 0;
389 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
390 case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
391 return 3;
392 case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE:
393 return 3;
394 case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE:
395 return 5;
396 case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
397 return 1;
398 case PIPE_VIDEO_PROFILE_VC1_MAIN:
399 return 2;
400 case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
401 return 4;
402 case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
403 case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
404 case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
405 return 41;
406 default:
407 debug_printf("unknown video profile: %d\n", profile);
408 return 0;
409 }
410 default:
411 debug_printf("unknown video param: %d\n", param);
412 return 0;
413 }
414 }
415
416 boolean
417 nouveau_vp3_screen_video_supported(struct pipe_screen *screen,
418 enum pipe_format format,
419 enum pipe_video_profile profile,
420 enum pipe_video_entrypoint entrypoint)
421 {
422 if (profile != PIPE_VIDEO_PROFILE_UNKNOWN)
423 return format == PIPE_FORMAT_NV12;
424
425 return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint);
426 }