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 const int chipset = nouveau_screen(pscreen)->device->chipset;
440 /* Feature Set B = vp3, C = vp4, D = vp5 */
441 const bool vp3 = chipset < 0xa3 || chipset == 0xaa || chipset == 0xac;
442 const bool vp5 = chipset >= 0xd0;
443 enum pipe_video_format codec = u_reduce_video_profile(profile);
444 switch (param) {
445 case PIPE_VIDEO_CAP_SUPPORTED:
446 /* VP3 does not support MPEG4, VP4+ do. */
447 return entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM &&
448 profile >= PIPE_VIDEO_PROFILE_MPEG1 &&
449 profile < PIPE_VIDEO_PROFILE_HEVC_MAIN &&
450 (!vp3 || codec != PIPE_VIDEO_FORMAT_MPEG4) &&
451 firmware_present(pscreen, profile);
452 case PIPE_VIDEO_CAP_NPOT_TEXTURES:
453 return 1;
454 case PIPE_VIDEO_CAP_MAX_WIDTH:
455 switch (codec) {
456 case PIPE_VIDEO_FORMAT_MPEG12:
457 return vp5 ? 4032 : 2048;
458 case PIPE_VIDEO_FORMAT_MPEG4:
459 return 2048;
460 case PIPE_VIDEO_FORMAT_VC1:
461 return 2048;
462 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
463 if (vp3)
464 return 2032;
465 if (vp5)
466 return 4032;
467 return 2048; /* vp4 */
468 case PIPE_VIDEO_FORMAT_UNKNOWN:
469 return vp5 ? 4032 : 2048;
470 default:
471 debug_printf("unknown video codec: %d\n", codec);
472 return 0;
473 }
474 case PIPE_VIDEO_CAP_MAX_HEIGHT:
475 switch (codec) {
476 case PIPE_VIDEO_FORMAT_MPEG12:
477 return vp5 ? 4048 : 2048;
478 case PIPE_VIDEO_FORMAT_MPEG4:
479 return 2048;
480 case PIPE_VIDEO_FORMAT_VC1:
481 return 2048;
482 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
483 if (vp3)
484 return 2048;
485 if (vp5)
486 return 4080;
487 return 2048; /* vp4 */
488 case PIPE_VIDEO_FORMAT_UNKNOWN:
489 return vp5 ? 4080 : 2048;
490 default:
491 debug_printf("unknown video codec: %d\n", codec);
492 return 0;
493 }
494 case PIPE_VIDEO_CAP_PREFERED_FORMAT:
495 return PIPE_FORMAT_NV12;
496 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
497 case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
498 return true;
499 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
500 return false;
501 case PIPE_VIDEO_CAP_MAX_LEVEL:
502 switch (profile) {
503 case PIPE_VIDEO_PROFILE_MPEG1:
504 return 0;
505 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
506 case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
507 return 3;
508 case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE:
509 return 3;
510 case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE:
511 return 5;
512 case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
513 return 1;
514 case PIPE_VIDEO_PROFILE_VC1_MAIN:
515 return 2;
516 case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
517 return 4;
518 case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
519 case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE:
520 case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
521 case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
522 return 41;
523 default:
524 debug_printf("unknown video profile: %d\n", profile);
525 return 0;
526 }
527 case PIPE_VIDEO_CAP_MAX_MACROBLOCKS:
528 switch (codec) {
529 case PIPE_VIDEO_FORMAT_MPEG12:
530 return vp5 ? 65536 : 8192;
531 case PIPE_VIDEO_FORMAT_MPEG4:
532 return 8192;
533 case PIPE_VIDEO_FORMAT_VC1:
534 return 8190;
535 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
536 if (vp3)
537 return 8190;
538 if (vp5)
539 return 65536;
540 return 8192; /* vp4 */
541 default:
542 debug_printf("unknown video codec: %d\n", codec);
543 return 0;
544 }
545 default:
546 debug_printf("unknown video param: %d\n", param);
547 return 0;
548 }
549 }
550
551 bool
nouveau_vp3_screen_video_supported(struct pipe_screen * screen,enum pipe_format format,enum pipe_video_profile profile,enum pipe_video_entrypoint entrypoint)552 nouveau_vp3_screen_video_supported(struct pipe_screen *screen,
553 enum pipe_format format,
554 enum pipe_video_profile profile,
555 enum pipe_video_entrypoint entrypoint)
556 {
557 if (profile != PIPE_VIDEO_PROFILE_UNKNOWN)
558 return format == PIPE_FORMAT_NV12;
559
560 return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint);
561 }
562