Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv50/nv84_video.c
4574 views
1
/*
2
* Copyright 2013 Ilia Mirkin
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 <sys/types.h>
26
#include <fcntl.h>
27
28
#include "util/format/u_format.h"
29
#include "util/u_sampler.h"
30
#include "vl/vl_zscan.h"
31
32
#include "nv50/nv84_video.h"
33
34
static int
35
nv84_copy_firmware(const char *path, void *dest, ssize_t len)
36
{
37
int fd = open(path, O_RDONLY | O_CLOEXEC);
38
ssize_t r;
39
if (fd < 0) {
40
fprintf(stderr, "opening firmware file %s failed: %m\n", path);
41
return 1;
42
}
43
r = read(fd, dest, len);
44
close(fd);
45
46
if (r != len) {
47
fprintf(stderr, "reading firmware file %s failed: %m\n", path);
48
return 1;
49
}
50
51
return 0;
52
}
53
54
static int
55
filesize(const char *path)
56
{
57
int ret;
58
struct stat statbuf;
59
60
ret = stat(path, &statbuf);
61
if (ret)
62
return ret;
63
return statbuf.st_size;
64
}
65
66
static struct nouveau_bo *
67
nv84_load_firmwares(struct nouveau_device *dev, struct nv84_decoder *dec,
68
const char *fw1, const char *fw2)
69
{
70
int ret, size1, size2 = 0;
71
struct nouveau_bo *fw;
72
73
size1 = filesize(fw1);
74
if (fw2)
75
size2 = filesize(fw2);
76
if (size1 < 0 || size2 < 0)
77
return NULL;
78
79
dec->vp_fw2_offset = align(size1, 0x100);
80
81
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, dec->vp_fw2_offset + size2, NULL, &fw);
82
if (ret)
83
return NULL;
84
ret = nouveau_bo_map(fw, NOUVEAU_BO_WR, dec->client);
85
if (ret)
86
goto error;
87
88
ret = nv84_copy_firmware(fw1, fw->map, size1);
89
if (fw2 && !ret)
90
ret = nv84_copy_firmware(fw2, fw->map + dec->vp_fw2_offset, size2);
91
munmap(fw->map, fw->size);
92
fw->map = NULL;
93
if (!ret)
94
return fw;
95
error:
96
nouveau_bo_ref(NULL, &fw);
97
return NULL;
98
}
99
100
static struct nouveau_bo *
101
nv84_load_bsp_firmware(struct nouveau_device *dev, struct nv84_decoder *dec)
102
{
103
return nv84_load_firmwares(
104
dev, dec, "/lib/firmware/nouveau/nv84_bsp-h264", NULL);
105
}
106
107
static struct nouveau_bo *
108
nv84_load_vp_firmware(struct nouveau_device *dev, struct nv84_decoder *dec)
109
{
110
return nv84_load_firmwares(
111
dev, dec,
112
"/lib/firmware/nouveau/nv84_vp-h264-1",
113
"/lib/firmware/nouveau/nv84_vp-h264-2");
114
}
115
116
static struct nouveau_bo *
117
nv84_load_vp_firmware_mpeg(struct nouveau_device *dev, struct nv84_decoder *dec)
118
{
119
return nv84_load_firmwares(
120
dev, dec, "/lib/firmware/nouveau/nv84_vp-mpeg12", NULL);
121
}
122
123
static void
124
nv84_decoder_decode_bitstream_h264(struct pipe_video_codec *decoder,
125
struct pipe_video_buffer *video_target,
126
struct pipe_picture_desc *picture,
127
unsigned num_buffers,
128
const void *const *data,
129
const unsigned *num_bytes)
130
{
131
struct nv84_decoder *dec = (struct nv84_decoder *)decoder;
132
struct nv84_video_buffer *target = (struct nv84_video_buffer *)video_target;
133
134
struct pipe_h264_picture_desc *desc = (struct pipe_h264_picture_desc *)picture;
135
136
assert(target->base.buffer_format == PIPE_FORMAT_NV12);
137
138
nv84_decoder_bsp(dec, desc, num_buffers, data, num_bytes, target);
139
nv84_decoder_vp_h264(dec, desc, target);
140
}
141
142
static void
143
nv84_decoder_flush(struct pipe_video_codec *decoder)
144
{
145
}
146
147
static void
148
nv84_decoder_begin_frame_h264(struct pipe_video_codec *decoder,
149
struct pipe_video_buffer *target,
150
struct pipe_picture_desc *picture)
151
{
152
}
153
154
static void
155
nv84_decoder_end_frame_h264(struct pipe_video_codec *decoder,
156
struct pipe_video_buffer *target,
157
struct pipe_picture_desc *picture)
158
{
159
}
160
161
static void
162
nv84_decoder_decode_bitstream_mpeg12(struct pipe_video_codec *decoder,
163
struct pipe_video_buffer *video_target,
164
struct pipe_picture_desc *picture,
165
unsigned num_buffers,
166
const void *const *data,
167
const unsigned *num_bytes)
168
{
169
struct nv84_decoder *dec = (struct nv84_decoder *)decoder;
170
171
assert(video_target->buffer_format == PIPE_FORMAT_NV12);
172
173
vl_mpg12_bs_decode(dec->mpeg12_bs,
174
video_target,
175
(struct pipe_mpeg12_picture_desc *)picture,
176
num_buffers,
177
data,
178
num_bytes);
179
}
180
181
static void
182
nv84_decoder_begin_frame_mpeg12(struct pipe_video_codec *decoder,
183
struct pipe_video_buffer *target,
184
struct pipe_picture_desc *picture)
185
{
186
struct nv84_decoder *dec = (struct nv84_decoder *)decoder;
187
struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture;
188
int i;
189
190
nouveau_bo_wait(dec->mpeg12_bo, NOUVEAU_BO_RDWR, dec->client);
191
dec->mpeg12_mb_info = dec->mpeg12_bo->map + 0x100;
192
dec->mpeg12_data = dec->mpeg12_bo->map + 0x100 +
193
align(0x20 * mb(dec->base.width) * mb(dec->base.height), 0x100);
194
if (desc->intra_matrix) {
195
dec->zscan = desc->alternate_scan ? vl_zscan_alternate : vl_zscan_normal;
196
for (i = 0; i < 64; i++) {
197
dec->mpeg12_intra_matrix[i] = desc->intra_matrix[dec->zscan[i]];
198
dec->mpeg12_non_intra_matrix[i] = desc->non_intra_matrix[dec->zscan[i]];
199
}
200
dec->mpeg12_intra_matrix[0] = 1 << (7 - desc->intra_dc_precision);
201
}
202
}
203
204
static void
205
nv84_decoder_end_frame_mpeg12(struct pipe_video_codec *decoder,
206
struct pipe_video_buffer *target,
207
struct pipe_picture_desc *picture)
208
{
209
nv84_decoder_vp_mpeg12(
210
(struct nv84_decoder *)decoder,
211
(struct pipe_mpeg12_picture_desc *)picture,
212
(struct nv84_video_buffer *)target);
213
}
214
215
static void
216
nv84_decoder_decode_macroblock(struct pipe_video_codec *decoder,
217
struct pipe_video_buffer *target,
218
struct pipe_picture_desc *picture,
219
const struct pipe_macroblock *macroblocks,
220
unsigned num_macroblocks)
221
{
222
const struct pipe_mpeg12_macroblock *mb = (const struct pipe_mpeg12_macroblock *)macroblocks;
223
for (int i = 0; i < num_macroblocks; i++, mb++) {
224
nv84_decoder_vp_mpeg12_mb(
225
(struct nv84_decoder *)decoder,
226
(struct pipe_mpeg12_picture_desc *)picture,
227
mb);
228
}
229
}
230
231
static void
232
nv84_decoder_destroy(struct pipe_video_codec *decoder)
233
{
234
struct nv84_decoder *dec = (struct nv84_decoder *)decoder;
235
236
nouveau_bo_ref(NULL, &dec->bsp_fw);
237
nouveau_bo_ref(NULL, &dec->bsp_data);
238
nouveau_bo_ref(NULL, &dec->vp_fw);
239
nouveau_bo_ref(NULL, &dec->vp_data);
240
nouveau_bo_ref(NULL, &dec->mbring);
241
nouveau_bo_ref(NULL, &dec->vpring);
242
nouveau_bo_ref(NULL, &dec->bitstream);
243
nouveau_bo_ref(NULL, &dec->vp_params);
244
nouveau_bo_ref(NULL, &dec->fence);
245
246
nouveau_object_del(&dec->bsp);
247
nouveau_object_del(&dec->vp);
248
249
nouveau_bufctx_del(&dec->bsp_bufctx);
250
nouveau_pushbuf_del(&dec->bsp_pushbuf);
251
nouveau_object_del(&dec->bsp_channel);
252
253
nouveau_bufctx_del(&dec->vp_bufctx);
254
nouveau_pushbuf_del(&dec->vp_pushbuf);
255
nouveau_object_del(&dec->vp_channel);
256
257
nouveau_client_del(&dec->client);
258
259
FREE(dec->mpeg12_bs);
260
FREE(dec);
261
}
262
263
struct pipe_video_codec *
264
nv84_create_decoder(struct pipe_context *context,
265
const struct pipe_video_codec *templ)
266
{
267
struct nv50_context *nv50 = (struct nv50_context *)context;
268
struct nouveau_screen *screen = &nv50->screen->base;
269
struct nv84_decoder *dec;
270
struct nouveau_pushbuf *bsp_push, *vp_push;
271
struct nv50_surface surf;
272
struct nv50_miptree mip;
273
union pipe_color_union color;
274
struct nv04_fifo nv04_data = { .vram = 0xbeef0201, .gart = 0xbeef0202 };
275
int ret, i;
276
int is_h264 = u_reduce_video_profile(templ->profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC;
277
int is_mpeg12 = u_reduce_video_profile(templ->profile) == PIPE_VIDEO_FORMAT_MPEG12;
278
279
if (getenv("XVMC_VL"))
280
return vl_create_decoder(context, templ);
281
282
if ((is_h264 && templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) ||
283
(is_mpeg12 && templ->entrypoint > PIPE_VIDEO_ENTRYPOINT_IDCT)) {
284
debug_printf("%x\n", templ->entrypoint);
285
return NULL;
286
}
287
288
if (!is_h264 && !is_mpeg12) {
289
debug_printf("invalid profile: %x\n", templ->profile);
290
return NULL;
291
}
292
293
dec = CALLOC_STRUCT(nv84_decoder);
294
if (!dec)
295
return NULL;
296
297
dec->base = *templ;
298
dec->base.context = context;
299
dec->base.destroy = nv84_decoder_destroy;
300
dec->base.flush = nv84_decoder_flush;
301
if (is_h264) {
302
dec->base.decode_bitstream = nv84_decoder_decode_bitstream_h264;
303
dec->base.begin_frame = nv84_decoder_begin_frame_h264;
304
dec->base.end_frame = nv84_decoder_end_frame_h264;
305
306
dec->frame_mbs = mb(dec->base.width) * mb_half(dec->base.height) * 2;
307
dec->frame_size = dec->frame_mbs << 8;
308
dec->vpring_deblock = align(0x30 * dec->frame_mbs, 0x100);
309
dec->vpring_residual = 0x2000 + MAX2(0x32000, 0x600 * dec->frame_mbs);
310
dec->vpring_ctrl = MAX2(0x10000, align(0x1080 + 0x144 * dec->frame_mbs, 0x100));
311
} else if (is_mpeg12) {
312
dec->base.decode_macroblock = nv84_decoder_decode_macroblock;
313
dec->base.begin_frame = nv84_decoder_begin_frame_mpeg12;
314
dec->base.end_frame = nv84_decoder_end_frame_mpeg12;
315
316
if (templ->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
317
dec->mpeg12_bs = CALLOC_STRUCT(vl_mpg12_bs);
318
if (!dec->mpeg12_bs)
319
goto fail;
320
vl_mpg12_bs_init(dec->mpeg12_bs, &dec->base);
321
dec->base.decode_bitstream = nv84_decoder_decode_bitstream_mpeg12;
322
}
323
} else {
324
goto fail;
325
}
326
327
ret = nouveau_client_new(screen->device, &dec->client);
328
if (ret)
329
goto fail;
330
331
if (is_h264) {
332
ret = nouveau_object_new(&screen->device->object, 0,
333
NOUVEAU_FIFO_CHANNEL_CLASS,
334
&nv04_data, sizeof(nv04_data), &dec->bsp_channel);
335
if (ret)
336
goto fail;
337
338
ret = nouveau_pushbuf_new(dec->client, dec->bsp_channel, 4,
339
32 * 1024, true, &dec->bsp_pushbuf);
340
if (ret)
341
goto fail;
342
343
ret = nouveau_bufctx_new(dec->client, 1, &dec->bsp_bufctx);
344
if (ret)
345
goto fail;
346
}
347
348
ret = nouveau_object_new(&screen->device->object, 0,
349
NOUVEAU_FIFO_CHANNEL_CLASS,
350
&nv04_data, sizeof(nv04_data), &dec->vp_channel);
351
if (ret)
352
goto fail;
353
ret = nouveau_pushbuf_new(dec->client, dec->vp_channel, 4,
354
32 * 1024, true, &dec->vp_pushbuf);
355
if (ret)
356
goto fail;
357
358
ret = nouveau_bufctx_new(dec->client, 1, &dec->vp_bufctx);
359
if (ret)
360
goto fail;
361
362
bsp_push = dec->bsp_pushbuf;
363
vp_push = dec->vp_pushbuf;
364
365
if (is_h264) {
366
dec->bsp_fw = nv84_load_bsp_firmware(screen->device, dec);
367
dec->vp_fw = nv84_load_vp_firmware(screen->device, dec);
368
if (!dec->bsp_fw || !dec->vp_fw)
369
goto fail;
370
}
371
if (is_mpeg12) {
372
dec->vp_fw = nv84_load_vp_firmware_mpeg(screen->device, dec);
373
if (!dec->vp_fw)
374
goto fail;
375
}
376
377
if (is_h264) {
378
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP,
379
0, 0x40000, NULL, &dec->bsp_data);
380
if (ret)
381
goto fail;
382
}
383
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP,
384
0, 0x40000, NULL, &dec->vp_data);
385
if (ret)
386
goto fail;
387
if (is_h264) {
388
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP,
389
0,
390
2 * (dec->vpring_deblock +
391
dec->vpring_residual +
392
dec->vpring_ctrl +
393
0x1000),
394
NULL, &dec->vpring);
395
if (ret)
396
goto fail;
397
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP,
398
0,
399
(templ->max_references + 1) * dec->frame_mbs * 0x40 +
400
dec->frame_size + 0x2000,
401
NULL, &dec->mbring);
402
if (ret)
403
goto fail;
404
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART,
405
0, 2 * (0x700 + MAX2(0x40000, 0x800 + 0x180 * dec->frame_mbs)),
406
NULL, &dec->bitstream);
407
if (ret)
408
goto fail;
409
ret = nouveau_bo_map(dec->bitstream, NOUVEAU_BO_WR, dec->client);
410
if (ret)
411
goto fail;
412
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART,
413
0, 0x2000, NULL, &dec->vp_params);
414
if (ret)
415
goto fail;
416
ret = nouveau_bo_map(dec->vp_params, NOUVEAU_BO_WR, dec->client);
417
if (ret)
418
goto fail;
419
}
420
if (is_mpeg12) {
421
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART,
422
0,
423
align(0x20 * mb(templ->width) * mb(templ->height), 0x100) +
424
(6 * 64 * 8) * mb(templ->width) * mb(templ->height) + 0x100,
425
NULL, &dec->mpeg12_bo);
426
if (ret)
427
goto fail;
428
ret = nouveau_bo_map(dec->mpeg12_bo, NOUVEAU_BO_WR, dec->client);
429
if (ret)
430
goto fail;
431
}
432
433
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
434
0, 0x1000, NULL, &dec->fence);
435
if (ret)
436
goto fail;
437
ret = nouveau_bo_map(dec->fence, NOUVEAU_BO_WR, dec->client);
438
if (ret)
439
goto fail;
440
*(uint32_t *)dec->fence->map = 0;
441
442
if (is_h264) {
443
nouveau_pushbuf_bufctx(bsp_push, dec->bsp_bufctx);
444
nouveau_bufctx_refn(dec->bsp_bufctx, 0,
445
dec->bsp_fw, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
446
nouveau_bufctx_refn(dec->bsp_bufctx, 0,
447
dec->bsp_data, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
448
}
449
450
nouveau_pushbuf_bufctx(vp_push, dec->vp_bufctx);
451
nouveau_bufctx_refn(dec->vp_bufctx, 0, dec->vp_fw,
452
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
453
nouveau_bufctx_refn(dec->vp_bufctx, 0, dec->vp_data,
454
NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
455
456
if (is_h264 && !ret)
457
ret = nouveau_object_new(dec->bsp_channel, 0xbeef74b0, 0x74b0,
458
NULL, 0, &dec->bsp);
459
460
if (!ret)
461
ret = nouveau_object_new(dec->vp_channel, 0xbeef7476, 0x7476,
462
NULL, 0, &dec->vp);
463
464
if (ret)
465
goto fail;
466
467
468
if (is_h264) {
469
/* Zero out some parts of mbring/vpring. there's gotta be some cleaner way
470
* of doing this... perhaps makes sense to just copy the relevant logic
471
* here. */
472
color.f[0] = color.f[1] = color.f[2] = color.f[3] = 0;
473
surf.offset = dec->frame_size;
474
surf.width = 64;
475
surf.height = (templ->max_references + 1) * dec->frame_mbs / 4;
476
surf.depth = 1;
477
surf.base.format = PIPE_FORMAT_B8G8R8A8_UNORM;
478
surf.base.u.tex.level = 0;
479
surf.base.texture = &mip.base.base;
480
mip.level[0].tile_mode = 0;
481
mip.level[0].pitch = surf.width * 4;
482
mip.base.domain = NOUVEAU_BO_VRAM;
483
mip.base.bo = dec->mbring;
484
mip.base.address = dec->mbring->offset;
485
context->clear_render_target(context, &surf.base, &color, 0, 0, 64, 4760, false);
486
surf.offset = dec->vpring->size / 2 - 0x1000;
487
surf.width = 1024;
488
surf.height = 1;
489
mip.level[0].pitch = surf.width * 4;
490
mip.base.bo = dec->vpring;
491
mip.base.address = dec->vpring->offset;
492
context->clear_render_target(context, &surf.base, &color, 0, 0, 1024, 1, false);
493
surf.offset = dec->vpring->size - 0x1000;
494
context->clear_render_target(context, &surf.base, &color, 0, 0, 1024, 1, false);
495
496
PUSH_SPACE(screen->pushbuf, 5);
497
PUSH_REFN(screen->pushbuf, dec->fence, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
498
/* The clear_render_target is done via 3D engine, so use it to write to a
499
* sempahore to indicate that it's done.
500
*/
501
BEGIN_NV04(screen->pushbuf, NV50_3D(QUERY_ADDRESS_HIGH), 4);
502
PUSH_DATAh(screen->pushbuf, dec->fence->offset);
503
PUSH_DATA (screen->pushbuf, dec->fence->offset);
504
PUSH_DATA (screen->pushbuf, 1);
505
PUSH_DATA (screen->pushbuf, 0xf010);
506
PUSH_KICK (screen->pushbuf);
507
508
PUSH_SPACE(bsp_push, 2 + 12 + 2 + 4 + 3);
509
510
BEGIN_NV04(bsp_push, SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
511
PUSH_DATA (bsp_push, dec->bsp->handle);
512
513
BEGIN_NV04(bsp_push, SUBC_BSP(0x180), 11);
514
for (i = 0; i < 11; i++)
515
PUSH_DATA(bsp_push, nv04_data.vram);
516
BEGIN_NV04(bsp_push, SUBC_BSP(0x1b8), 1);
517
PUSH_DATA (bsp_push, nv04_data.vram);
518
519
BEGIN_NV04(bsp_push, SUBC_BSP(0x600), 3);
520
PUSH_DATAh(bsp_push, dec->bsp_fw->offset);
521
PUSH_DATA (bsp_push, dec->bsp_fw->offset);
522
PUSH_DATA (bsp_push, dec->bsp_fw->size);
523
524
BEGIN_NV04(bsp_push, SUBC_BSP(0x628), 2);
525
PUSH_DATA (bsp_push, dec->bsp_data->offset >> 8);
526
PUSH_DATA (bsp_push, dec->bsp_data->size);
527
PUSH_KICK (bsp_push);
528
}
529
530
PUSH_SPACE(vp_push, 2 + 12 + 2 + 4 + 3);
531
532
BEGIN_NV04(vp_push, SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
533
PUSH_DATA (vp_push, dec->vp->handle);
534
535
BEGIN_NV04(vp_push, SUBC_VP(0x180), 11);
536
for (i = 0; i < 11; i++)
537
PUSH_DATA(vp_push, nv04_data.vram);
538
539
BEGIN_NV04(vp_push, SUBC_VP(0x1b8), 1);
540
PUSH_DATA (vp_push, nv04_data.vram);
541
542
BEGIN_NV04(vp_push, SUBC_VP(0x600), 3);
543
PUSH_DATAh(vp_push, dec->vp_fw->offset);
544
PUSH_DATA (vp_push, dec->vp_fw->offset);
545
PUSH_DATA (vp_push, dec->vp_fw->size);
546
547
BEGIN_NV04(vp_push, SUBC_VP(0x628), 2);
548
PUSH_DATA (vp_push, dec->vp_data->offset >> 8);
549
PUSH_DATA (vp_push, dec->vp_data->size);
550
PUSH_KICK (vp_push);
551
552
return &dec->base;
553
fail:
554
nv84_decoder_destroy(&dec->base);
555
return NULL;
556
}
557
558
static struct pipe_sampler_view **
559
nv84_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
560
{
561
struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer;
562
return buf->sampler_view_planes;
563
}
564
565
static struct pipe_sampler_view **
566
nv84_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
567
{
568
struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer;
569
return buf->sampler_view_components;
570
}
571
572
static struct pipe_surface **
573
nv84_video_buffer_surfaces(struct pipe_video_buffer *buffer)
574
{
575
struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer;
576
return buf->surfaces;
577
}
578
579
static void
580
nv84_video_buffer_destroy(struct pipe_video_buffer *buffer)
581
{
582
struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer;
583
unsigned i;
584
585
assert(buf);
586
587
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
588
pipe_resource_reference(&buf->resources[i], NULL);
589
pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
590
pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
591
pipe_surface_reference(&buf->surfaces[i * 2], NULL);
592
pipe_surface_reference(&buf->surfaces[i * 2 + 1], NULL);
593
}
594
595
nouveau_bo_ref(NULL, &buf->interlaced);
596
nouveau_bo_ref(NULL, &buf->full);
597
598
FREE(buffer);
599
}
600
601
struct pipe_video_buffer *
602
nv84_video_buffer_create(struct pipe_context *pipe,
603
const struct pipe_video_buffer *template)
604
{
605
struct nv84_video_buffer *buffer;
606
struct pipe_resource templ;
607
unsigned i, j, component;
608
struct pipe_sampler_view sv_templ;
609
struct pipe_surface surf_templ;
610
struct nv50_miptree *mt0, *mt1;
611
struct nouveau_screen *screen = &((struct nv50_context *)pipe)->screen->base;
612
union nouveau_bo_config cfg;
613
unsigned bo_size;
614
615
if (getenv("XVMC_VL") || template->buffer_format != PIPE_FORMAT_NV12)
616
return vl_video_buffer_create(pipe, template);
617
618
if (!template->interlaced) {
619
debug_printf("Require interlaced video buffers\n");
620
return NULL;
621
}
622
if (pipe_format_to_chroma_format(template->buffer_format) != PIPE_VIDEO_CHROMA_FORMAT_420) {
623
debug_printf("Must use 4:2:0 format\n");
624
return NULL;
625
}
626
627
/*
628
* Note that there are always going to be exactly two planes, one for Y,
629
* and one for UV. These are also the resources. VP expects these to be
630
* adjacent, so they need to belong to the same BO.
631
*/
632
633
buffer = CALLOC_STRUCT(nv84_video_buffer);
634
if (!buffer) return NULL;
635
636
buffer->mvidx = -1;
637
638
buffer->base.buffer_format = template->buffer_format;
639
buffer->base.context = pipe;
640
buffer->base.destroy = nv84_video_buffer_destroy;
641
buffer->base.width = template->width;
642
buffer->base.height = template->height;
643
buffer->base.get_sampler_view_planes = nv84_video_buffer_sampler_view_planes;
644
buffer->base.get_sampler_view_components = nv84_video_buffer_sampler_view_components;
645
buffer->base.get_surfaces = nv84_video_buffer_surfaces;
646
buffer->base.interlaced = true;
647
648
memset(&templ, 0, sizeof(templ));
649
templ.target = PIPE_TEXTURE_2D_ARRAY;
650
templ.depth0 = 1;
651
templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
652
templ.format = PIPE_FORMAT_R8_UNORM;
653
templ.width0 = align(template->width, 2);
654
templ.height0 = align(template->height, 4) / 2;
655
templ.flags = NV50_RESOURCE_FLAG_VIDEO | NV50_RESOURCE_FLAG_NOALLOC;
656
templ.array_size = 2;
657
658
cfg.nv50.tile_mode = 0x20;
659
cfg.nv50.memtype = 0x70;
660
661
buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ);
662
if (!buffer->resources[0])
663
goto error;
664
665
templ.format = PIPE_FORMAT_R8G8_UNORM;
666
templ.width0 /= 2;
667
templ.height0 /= 2;
668
buffer->resources[1] = pipe->screen->resource_create(pipe->screen, &templ);
669
if (!buffer->resources[1])
670
goto error;
671
672
mt0 = nv50_miptree(buffer->resources[0]);
673
mt1 = nv50_miptree(buffer->resources[1]);
674
675
bo_size = mt0->total_size + mt1->total_size;
676
if (nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP, 0,
677
bo_size, &cfg, &buffer->interlaced))
678
goto error;
679
/* XXX Change reference frame management so that this is only allocated in
680
* the decoder when necessary. */
681
if (nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP, 0,
682
bo_size, &cfg, &buffer->full))
683
goto error;
684
685
nouveau_bo_ref(buffer->interlaced, &mt0->base.bo);
686
mt0->base.domain = NOUVEAU_BO_VRAM;
687
mt0->base.address = buffer->interlaced->offset;
688
689
nouveau_bo_ref(buffer->interlaced, &mt1->base.bo);
690
mt1->base.domain = NOUVEAU_BO_VRAM;
691
mt1->base.offset = mt0->total_size;
692
mt1->base.address = buffer->interlaced->offset + mt0->total_size;
693
694
memset(&sv_templ, 0, sizeof(sv_templ));
695
for (component = 0, i = 0; i < 2; ++i ) {
696
struct pipe_resource *res = buffer->resources[i];
697
unsigned nr_components = util_format_get_nr_components(res->format);
698
699
u_sampler_view_default_template(&sv_templ, res, res->format);
700
buffer->sampler_view_planes[i] =
701
pipe->create_sampler_view(pipe, res, &sv_templ);
702
if (!buffer->sampler_view_planes[i])
703
goto error;
704
705
for (j = 0; j < nr_components; ++j, ++component) {
706
sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b =
707
PIPE_SWIZZLE_X + j;
708
sv_templ.swizzle_a = PIPE_SWIZZLE_1;
709
710
buffer->sampler_view_components[component] =
711
pipe->create_sampler_view(pipe, res, &sv_templ);
712
if (!buffer->sampler_view_components[component])
713
goto error;
714
}
715
}
716
717
memset(&surf_templ, 0, sizeof(surf_templ));
718
for (j = 0; j < 2; ++j) {
719
surf_templ.format = buffer->resources[j]->format;
720
surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 0;
721
buffer->surfaces[j * 2] =
722
pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
723
if (!buffer->surfaces[j * 2])
724
goto error;
725
726
surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 1;
727
buffer->surfaces[j * 2 + 1] =
728
pipe->create_surface(pipe, buffer->resources[j], &surf_templ);
729
if (!buffer->surfaces[j * 2 + 1])
730
goto error;
731
}
732
733
return &buffer->base;
734
735
error:
736
nv84_video_buffer_destroy(&buffer->base);
737
return NULL;
738
}
739
740
#define FIRMWARE_BSP_KERN 0x01
741
#define FIRMWARE_VP_KERN 0x02
742
#define FIRMWARE_BSP_H264 0x04
743
#define FIRMWARE_VP_MPEG2 0x08
744
#define FIRMWARE_VP_H264_1 0x10
745
#define FIRMWARE_VP_H264_2 0x20
746
#define FIRMWARE_PRESENT(val, fw) (val & FIRMWARE_ ## fw)
747
748
static int
749
firmware_present(struct pipe_screen *pscreen, enum pipe_video_format codec)
750
{
751
struct nouveau_screen *screen = nouveau_screen(pscreen);
752
struct nouveau_object *obj = NULL;
753
struct stat s;
754
int checked = screen->firmware_info.profiles_checked;
755
int present, ret;
756
757
if (!FIRMWARE_PRESENT(checked, VP_KERN)) {
758
ret = nouveau_object_new(screen->channel, 0, 0x7476, NULL, 0, &obj);
759
if (!ret)
760
screen->firmware_info.profiles_present |= FIRMWARE_VP_KERN;
761
nouveau_object_del(&obj);
762
screen->firmware_info.profiles_checked |= FIRMWARE_VP_KERN;
763
}
764
765
if (codec == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
766
if (!FIRMWARE_PRESENT(checked, BSP_KERN)) {
767
ret = nouveau_object_new(screen->channel, 0, 0x74b0, NULL, 0, &obj);
768
if (!ret)
769
screen->firmware_info.profiles_present |= FIRMWARE_BSP_KERN;
770
nouveau_object_del(&obj);
771
screen->firmware_info.profiles_checked |= FIRMWARE_BSP_KERN;
772
}
773
774
if (!FIRMWARE_PRESENT(checked, VP_H264_1)) {
775
ret = stat("/lib/firmware/nouveau/nv84_vp-h264-1", &s);
776
if (!ret && s.st_size > 1000)
777
screen->firmware_info.profiles_present |= FIRMWARE_VP_H264_1;
778
screen->firmware_info.profiles_checked |= FIRMWARE_VP_H264_1;
779
}
780
781
/* should probably check the others, but assume that 1 means all */
782
783
present = screen->firmware_info.profiles_present;
784
return FIRMWARE_PRESENT(present, VP_KERN) &&
785
FIRMWARE_PRESENT(present, BSP_KERN) &&
786
FIRMWARE_PRESENT(present, VP_H264_1);
787
} else {
788
if (!FIRMWARE_PRESENT(checked, VP_MPEG2)) {
789
ret = stat("/lib/firmware/nouveau/nv84_vp-mpeg12", &s);
790
if (!ret && s.st_size > 1000)
791
screen->firmware_info.profiles_present |= FIRMWARE_VP_MPEG2;
792
screen->firmware_info.profiles_checked |= FIRMWARE_VP_MPEG2;
793
}
794
present = screen->firmware_info.profiles_present;
795
return FIRMWARE_PRESENT(present, VP_KERN) &&
796
FIRMWARE_PRESENT(present, VP_MPEG2);
797
}
798
}
799
800
int
801
nv84_screen_get_video_param(struct pipe_screen *pscreen,
802
enum pipe_video_profile profile,
803
enum pipe_video_entrypoint entrypoint,
804
enum pipe_video_cap param)
805
{
806
enum pipe_video_format codec;
807
808
switch (param) {
809
case PIPE_VIDEO_CAP_SUPPORTED:
810
codec = u_reduce_video_profile(profile);
811
return (codec == PIPE_VIDEO_FORMAT_MPEG4_AVC ||
812
codec == PIPE_VIDEO_FORMAT_MPEG12) &&
813
firmware_present(pscreen, codec);
814
case PIPE_VIDEO_CAP_NPOT_TEXTURES:
815
return 1;
816
case PIPE_VIDEO_CAP_MAX_WIDTH:
817
case PIPE_VIDEO_CAP_MAX_HEIGHT:
818
return 2048;
819
case PIPE_VIDEO_CAP_PREFERED_FORMAT:
820
return PIPE_FORMAT_NV12;
821
case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
822
case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
823
return true;
824
case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
825
return false;
826
case PIPE_VIDEO_CAP_MAX_LEVEL:
827
switch (profile) {
828
case PIPE_VIDEO_PROFILE_MPEG1:
829
return 0;
830
case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
831
case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
832
return 3;
833
case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
834
case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
835
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
836
return 41;
837
default:
838
debug_printf("unknown video profile: %d\n", profile);
839
return 0;
840
}
841
case PIPE_VIDEO_CAP_MAX_MACROBLOCKS:
842
return 8192; /* vc-1 actually has 8190, but this is not supported */
843
default:
844
debug_printf("unknown video param: %d\n", param);
845
return 0;
846
}
847
}
848
849
bool
850
nv84_screen_video_supported(struct pipe_screen *screen,
851
enum pipe_format format,
852
enum pipe_video_profile profile,
853
enum pipe_video_entrypoint entrypoint)
854
{
855
if (profile != PIPE_VIDEO_PROFILE_UNKNOWN)
856
return format == PIPE_FORMAT_NV12;
857
858
return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint);
859
}
860
861