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