• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <sys/stat.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 
28 #include <nvif/class.h>
29 
30 #include "nouveau_screen.h"
31 #include "nouveau_context.h"
32 #include "nouveau_vp3_video.h"
33 
34 #include "util/u_video.h"
35 #include "util/format/u_format.h"
36 #include "util/u_sampler.h"
37 
38 static struct pipe_sampler_view **
nouveau_vp3_video_buffer_sampler_view_planes(struct pipe_video_buffer * buffer)39 nouveau_vp3_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
40 {
41    struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
42    return buf->sampler_view_planes;
43 }
44 
45 static struct pipe_sampler_view **
nouveau_vp3_video_buffer_sampler_view_components(struct pipe_video_buffer * buffer)46 nouveau_vp3_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
47 {
48    struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
49    return buf->sampler_view_components;
50 }
51 
52 static struct pipe_surface **
nouveau_vp3_video_buffer_surfaces(struct pipe_video_buffer * buffer)53 nouveau_vp3_video_buffer_surfaces(struct pipe_video_buffer *buffer)
54 {
55    struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
56    return buf->surfaces;
57 }
58 
59 static void
nouveau_vp3_video_buffer_destroy(struct pipe_video_buffer * buffer)60 nouveau_vp3_video_buffer_destroy(struct pipe_video_buffer *buffer)
61 {
62    struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer;
63    unsigned i;
64 
65    assert(buf);
66 
67    for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
68       pipe_resource_reference(&buf->resources[i], NULL);
69       pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
70       pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
71       pipe_surface_reference(&buf->surfaces[i * 2], NULL);
72       pipe_surface_reference(&buf->surfaces[i * 2 + 1], NULL);
73    }
74    FREE(buffer);
75 }
76 
77 struct pipe_video_buffer *
nouveau_vp3_video_buffer_create(struct pipe_context * pipe,const struct pipe_video_buffer * templat,int flags)78 nouveau_vp3_video_buffer_create(struct pipe_context *pipe,
79                          const struct pipe_video_buffer *templat,
80                          int flags)
81 {
82    struct nouveau_vp3_video_buffer *buffer;
83    struct pipe_resource templ;
84    unsigned i, j, component;
85    struct pipe_sampler_view sv_templ;
86    struct pipe_surface surf_templ;
87 
88    if (getenv("XVMC_VL") || templat->buffer_format != PIPE_FORMAT_NV12)
89       return vl_video_buffer_create(pipe, templat);
90 
91    assert(templat->interlaced);
92    assert(pipe_format_to_chroma_format(templat->buffer_format) == PIPE_VIDEO_CHROMA_FORMAT_420);
93 
94    buffer = CALLOC_STRUCT(nouveau_vp3_video_buffer);
95    if (!buffer)
96       return NULL;
97 
98    buffer->base.buffer_format = templat->buffer_format;
99    buffer->base.context = pipe;
100    buffer->base.destroy = nouveau_vp3_video_buffer_destroy;
101    buffer->base.width = templat->width;
102    buffer->base.height = templat->height;
103    buffer->base.get_sampler_view_planes = nouveau_vp3_video_buffer_sampler_view_planes;
104    buffer->base.get_sampler_view_components = nouveau_vp3_video_buffer_sampler_view_components;
105    buffer->base.get_surfaces = nouveau_vp3_video_buffer_surfaces;
106    buffer->base.interlaced = true;
107 
108    memset(&templ, 0, sizeof(templ));
109    templ.target = PIPE_TEXTURE_2D_ARRAY;
110    templ.depth0 = 1;
111    templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
112    templ.format = PIPE_FORMAT_R8_UNORM;
113    templ.width0 = buffer->base.width;
114    templ.height0 = (buffer->base.height + 1)/2;
115    templ.flags = flags;
116    templ.array_size = 2;
117 
118    buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ);
119    if (!buffer->resources[0])
120       goto error;
121 
122    templ.format = PIPE_FORMAT_R8G8_UNORM;
123    buffer->num_planes = 2;
124    templ.width0 = (templ.width0 + 1) / 2;
125    templ.height0 = (templ.height0 + 1) / 2;
126    for (i = 1; i < buffer->num_planes; ++i) {
127       buffer->resources[i] = pipe->screen->resource_create(pipe->screen, &templ);
128       if (!buffer->resources[i])
129          goto error;
130    }
131 
132    memset(&sv_templ, 0, sizeof(sv_templ));
133    for (component = 0, i = 0; i < buffer->num_planes; ++i ) {
134       struct pipe_resource *res = buffer->resources[i];
135       unsigned nr_components = util_format_get_nr_components(res->format);
136 
137       u_sampler_view_default_template(&sv_templ, res, res->format);
138       buffer->sampler_view_planes[i] = pipe->create_sampler_view(pipe, res, &sv_templ);
139       if (!buffer->sampler_view_planes[i])
140          goto error;
141 
142       for (j = 0; j < nr_components; ++j, ++component) {
143          sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_X + j;
144          sv_templ.swizzle_a = PIPE_SWIZZLE_1;
145 
146          buffer->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
147          if (!buffer->sampler_view_components[component])
148             goto error;
149       }
150   }
151 
152    memset(&surf_templ, 0, sizeof(surf_templ));
153    for (j = 0; j < buffer->num_planes; ++j) {
154       surf_templ.format = buffer->resources[j]->format;
155       surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 0;
156       buffer->surfaces[j * 2] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
157       if (!buffer->surfaces[j * 2])
158          goto error;
159 
160       surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 1;
161       buffer->surfaces[j * 2 + 1] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
162       if (!buffer->surfaces[j * 2 + 1])
163          goto error;
164    }
165 
166    return &buffer->base;
167 
168 error:
169    nouveau_vp3_video_buffer_destroy(&buffer->base);
170    return NULL;
171 }
172 
173 static void
nouveau_vp3_decoder_flush(struct pipe_video_codec * decoder)174 nouveau_vp3_decoder_flush(struct pipe_video_codec *decoder)
175 {
176 }
177 
178 static void
nouveau_vp3_decoder_begin_frame(struct pipe_video_codec * decoder,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)179 nouveau_vp3_decoder_begin_frame(struct pipe_video_codec *decoder,
180                                 struct pipe_video_buffer *target,
181                                 struct pipe_picture_desc *picture)
182 {
183 }
184 
185 static void
nouveau_vp3_decoder_end_frame(struct pipe_video_codec * decoder,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)186 nouveau_vp3_decoder_end_frame(struct pipe_video_codec *decoder,
187                               struct pipe_video_buffer *target,
188                               struct pipe_picture_desc *picture)
189 {
190 }
191 
192 static void
nouveau_vp3_decoder_destroy(struct pipe_video_codec * decoder)193 nouveau_vp3_decoder_destroy(struct pipe_video_codec *decoder)
194 {
195    struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
196    int i;
197 
198    nouveau_bo_ref(NULL, &dec->ref_bo);
199    nouveau_bo_ref(NULL, &dec->bitplane_bo);
200    nouveau_bo_ref(NULL, &dec->inter_bo[0]);
201    nouveau_bo_ref(NULL, &dec->inter_bo[1]);
202 #if NOUVEAU_VP3_DEBUG_FENCE
203    nouveau_bo_ref(NULL, &dec->fence_bo);
204 #endif
205    nouveau_bo_ref(NULL, &dec->fw_bo);
206 
207    for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH; ++i)
208       nouveau_bo_ref(NULL, &dec->bsp_bo[i]);
209 
210    nouveau_object_del(&dec->bsp);
211    nouveau_object_del(&dec->vp);
212    nouveau_object_del(&dec->ppp);
213 
214    if (dec->channel[0] != dec->channel[1]) {
215       for (i = 0; i < 3; ++i) {
216          nouveau_pushbuf_del(&dec->pushbuf[i]);
217          nouveau_object_del(&dec->channel[i]);
218       }
219    } else {
220       nouveau_pushbuf_del(dec->pushbuf);
221       nouveau_object_del(dec->channel);
222    }
223 
224    FREE(dec);
225 }
226 
227 void
nouveau_vp3_decoder_init_common(struct pipe_video_codec * dec)228 nouveau_vp3_decoder_init_common(struct pipe_video_codec *dec)
229 {
230    dec->destroy = nouveau_vp3_decoder_destroy;
231    dec->flush = nouveau_vp3_decoder_flush;
232    dec->begin_frame = nouveau_vp3_decoder_begin_frame;
233    dec->end_frame = nouveau_vp3_decoder_end_frame;
234 }
235 
vp3_getpath(enum pipe_video_profile profile,char * path)236 static void vp3_getpath(enum pipe_video_profile profile, char *path)
237 {
238    switch (u_reduce_video_profile(profile)) {
239       case PIPE_VIDEO_FORMAT_MPEG12: {
240          sprintf(path, "/lib/firmware/nouveau/vuc-vp3-mpeg12-0");
241          break;
242       }
243       case PIPE_VIDEO_FORMAT_VC1: {
244          sprintf(path, "/lib/firmware/nouveau/vuc-vp3-vc1-0");
245          break;
246       }
247       case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
248          sprintf(path, "/lib/firmware/nouveau/vuc-vp3-h264-0");
249          break;
250       }
251       default: assert(0);
252    }
253 }
254 
vp4_getpath(enum pipe_video_profile profile,char * path)255 static void vp4_getpath(enum pipe_video_profile profile, char *path)
256 {
257    switch (u_reduce_video_profile(profile)) {
258       case PIPE_VIDEO_FORMAT_MPEG12: {
259          sprintf(path, "/lib/firmware/nouveau/vuc-mpeg12-0");
260          break;
261       }
262       case PIPE_VIDEO_FORMAT_MPEG4: {
263          sprintf(path, "/lib/firmware/nouveau/vuc-mpeg4-0");
264          break;
265       }
266       case PIPE_VIDEO_FORMAT_VC1: {
267          sprintf(path, "/lib/firmware/nouveau/vuc-vc1-0");
268          break;
269       }
270       case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
271          sprintf(path, "/lib/firmware/nouveau/vuc-h264-0");
272          break;
273       }
274       default: assert(0);
275    }
276 }
277 
278 int
nouveau_vp3_load_firmware(struct nouveau_vp3_decoder * dec,enum pipe_video_profile profile,unsigned chipset)279 nouveau_vp3_load_firmware(struct nouveau_vp3_decoder *dec,
280                           enum pipe_video_profile profile,
281                           unsigned chipset)
282 {
283    int fd;
284    char path[PATH_MAX];
285    ssize_t r;
286    uint32_t *end, endval;
287 
288    if (chipset >= 0xa3 && chipset != 0xaa && chipset != 0xac)
289       vp4_getpath(profile, path);
290    else
291       vp3_getpath(profile, path);
292 
293    if (nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client))
294       return 1;
295 
296    fd = open(path, O_RDONLY | O_CLOEXEC);
297    if (fd < 0) {
298       fprintf(stderr, "opening firmware file %s failed: %m\n", path);
299       return 1;
300    }
301    r = read(fd, dec->fw_bo->map, 0x4000);
302    close(fd);
303 
304    if (r < 0) {
305       fprintf(stderr, "reading firmware file %s failed: %m\n", path);
306       return 1;
307    }
308 
309    if (r == 0x4000) {
310       fprintf(stderr, "firmware file %s too large!\n", path);
311       return 1;
312    }
313 
314    if (r & 0xff) {
315       fprintf(stderr, "firmware file %s wrong size!\n", path);
316       return 1;
317    }
318 
319    end = dec->fw_bo->map + r - 4;
320    endval = *end;
321    while (endval == *end)
322       end--;
323 
324    r = (intptr_t)end - (intptr_t)dec->fw_bo->map + 4;
325 
326    switch (u_reduce_video_profile(profile)) {
327       case PIPE_VIDEO_FORMAT_MPEG12: {
328          assert((r & 0xff) == 0xe0);
329          dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
330          break;
331       }
332       case PIPE_VIDEO_FORMAT_MPEG4: {
333          assert((r & 0xff) == 0xe0);
334          dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
335          break;
336       }
337       case PIPE_VIDEO_FORMAT_VC1: {
338          assert((r & 0xff) == 0xac);
339          dec->fw_sizes = (0x3ac<<16) | (r - 0x3ac);
340          break;
341       }
342       case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
343          assert((r & 0xff) == 0x70);
344          dec->fw_sizes = (0x370<<16) | (r - 0x370);
345          break;
346       }
347       default:
348          return 1;
349    }
350    munmap(dec->fw_bo->map, dec->fw_bo->size);
351    dec->fw_bo->map = NULL;
352    return 0;
353 }
354 
355 static const struct nouveau_mclass
356 nouveau_decoder_msvld[] = {
357    { G98_MSVLD, -1 },
358    { IGT21A_MSVLD, -1 },
359    { GT212_MSVLD, -1 },
360    { GF100_MSVLD, -1 },
361    { GK104_MSVLD, -1 },
362    {}
363 };
364 
365 static int
firmware_present(struct pipe_screen * pscreen,enum pipe_video_profile profile)366 firmware_present(struct pipe_screen *pscreen, enum pipe_video_profile profile)
367 {
368    struct nouveau_screen *screen = nouveau_screen(pscreen);
369    int chipset = screen->device->chipset;
370    int vp3 = chipset < 0xa3 || chipset == 0xaa || chipset == 0xac;
371    int vp5 = chipset >= 0xd0;
372    int ret;
373 
374    /* For all chipsets, try to create a BSP objects. Assume that if firmware
375     * is present for it, firmware is also present for VP/PPP */
376    if (!(screen->firmware_info.profiles_checked & 1)) {
377       struct nouveau_object *channel = NULL, *bsp = NULL;
378       struct nv04_fifo nv04_data = {.vram = 0xbeef0201, .gart = 0xbeef0202};
379       struct nvc0_fifo nvc0_args = {};
380       struct nve0_fifo nve0_args = {.engine = NVE0_FIFO_ENGINE_BSP};
381       void *data = NULL;
382       int size;
383 
384       if (chipset < 0xc0) {
385          data = &nv04_data;
386          size = sizeof(nv04_data);
387       } else if (chipset < 0xe0) {
388          data = &nvc0_args;
389          size = sizeof(nvc0_args);
390       } else {
391          data = &nve0_args;
392          size = sizeof(nve0_args);
393       }
394 
395       /* kepler must have its own channel, so just do this for everyone */
396       nouveau_object_new(&screen->device->object, 0,
397                          NOUVEAU_FIFO_CHANNEL_CLASS,
398                          data, size, &channel);
399 
400       if (channel) {
401          ret = nouveau_object_mclass(channel, nouveau_decoder_msvld);
402          if (ret >= 0)
403             nouveau_object_new(channel, 0, nouveau_decoder_msvld[ret].oclass,
404                                NULL, 0, &bsp);
405          if (bsp)
406             screen->firmware_info.profiles_present |= 1;
407          nouveau_object_del(&bsp);
408          nouveau_object_del(&channel);
409       }
410       screen->firmware_info.profiles_checked |= 1;
411    }
412 
413    if (!(screen->firmware_info.profiles_present & 1))
414       return 0;
415 
416    /* For vp3/vp4 chipsets, make sure that the relevant firmware is present */
417    if (!vp5 && !(screen->firmware_info.profiles_checked & (1 << profile))) {
418       char path[PATH_MAX];
419       struct stat s;
420       if (vp3)
421          vp3_getpath(profile, path);
422       else
423          vp4_getpath(profile, path);
424       ret = stat(path, &s);
425       if (!ret && s.st_size > 1000)
426          screen->firmware_info.profiles_present |= (1 << profile);
427       screen->firmware_info.profiles_checked |= (1 << profile);
428    }
429 
430    return vp5 || (screen->firmware_info.profiles_present & (1 << profile));
431 }
432 
433 int
nouveau_vp3_screen_get_video_param(struct pipe_screen * pscreen,enum pipe_video_profile profile,enum pipe_video_entrypoint entrypoint,enum pipe_video_cap param)434 nouveau_vp3_screen_get_video_param(struct pipe_screen *pscreen,
435                                    enum pipe_video_profile profile,
436                                    enum pipe_video_entrypoint entrypoint,
437                                    enum pipe_video_cap param)
438 {
439    int chipset = nouveau_screen(pscreen)->device->chipset;
440    int vp3 = chipset < 0xa3 || chipset == 0xaa || chipset == 0xac;
441    int vp5 = chipset >= 0xd0;
442    enum pipe_video_format codec = u_reduce_video_profile(profile);
443    switch (param) {
444    case PIPE_VIDEO_CAP_SUPPORTED:
445       /* VP3 does not support MPEG4, VP4+ do. */
446       return entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM &&
447          profile >= PIPE_VIDEO_PROFILE_MPEG1 &&
448          profile < PIPE_VIDEO_PROFILE_HEVC_MAIN &&
449          (!vp3 || codec != PIPE_VIDEO_FORMAT_MPEG4) &&
450          firmware_present(pscreen, profile);
451    case PIPE_VIDEO_CAP_NPOT_TEXTURES:
452       return 1;
453    case PIPE_VIDEO_CAP_MAX_WIDTH:
454    case PIPE_VIDEO_CAP_MAX_HEIGHT:
455       return vp5 ? 4096 : 2048;
456    case PIPE_VIDEO_CAP_PREFERED_FORMAT:
457       return PIPE_FORMAT_NV12;
458    case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
459    case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
460       return true;
461    case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
462       return false;
463    case PIPE_VIDEO_CAP_MAX_LEVEL:
464       switch (profile) {
465       case PIPE_VIDEO_PROFILE_MPEG1:
466          return 0;
467       case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
468       case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
469          return 3;
470       case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE:
471          return 3;
472       case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE:
473          return 5;
474       case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
475          return 1;
476       case PIPE_VIDEO_PROFILE_VC1_MAIN:
477          return 2;
478       case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
479          return 4;
480       case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
481       case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
482       case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
483          return 41;
484       default:
485          debug_printf("unknown video profile: %d\n", profile);
486          return 0;
487       }
488    default:
489       debug_printf("unknown video param: %d\n", param);
490       return 0;
491    }
492 }
493 
494 bool
nouveau_vp3_screen_video_supported(struct pipe_screen * screen,enum pipe_format format,enum pipe_video_profile profile,enum pipe_video_entrypoint entrypoint)495 nouveau_vp3_screen_video_supported(struct pipe_screen *screen,
496                                    enum pipe_format format,
497                                    enum pipe_video_profile profile,
498                                    enum pipe_video_entrypoint entrypoint)
499 {
500    if (profile != PIPE_VIDEO_PROFILE_UNKNOWN)
501       return format == PIPE_FORMAT_NV12;
502 
503    return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint);
504 }
505