Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nouveau_vp3_video.c
4570 views
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 **
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 **
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 **
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
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 *
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
174
nouveau_vp3_decoder_flush(struct pipe_video_codec *decoder)
175
{
176
}
177
178
static void
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
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
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
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
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
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
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
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
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
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
563