Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nvc0/nvc0_video.c
4574 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 "nvc0/nvc0_video.h"
24
25
#include "util/u_sampler.h"
26
#include "util/format/u_format.h"
27
28
static void
29
nvc0_decoder_begin_frame(struct pipe_video_codec *decoder,
30
struct pipe_video_buffer *target,
31
struct pipe_picture_desc *picture)
32
{
33
struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
34
uint32_t comm_seq = ++dec->fence_seq;
35
ASSERTED unsigned ret = 0; /* used in debug checks */
36
37
assert(dec);
38
assert(target);
39
assert(target->buffer_format == PIPE_FORMAT_NV12);
40
41
ret = nvc0_decoder_bsp_begin(dec, comm_seq);
42
43
assert(ret == 2);
44
}
45
46
static void
47
nvc0_decoder_decode_bitstream(struct pipe_video_codec *decoder,
48
struct pipe_video_buffer *video_target,
49
struct pipe_picture_desc *picture,
50
unsigned num_buffers,
51
const void *const *data,
52
const unsigned *num_bytes)
53
{
54
struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
55
uint32_t comm_seq = dec->fence_seq;
56
ASSERTED unsigned ret = 0; /* used in debug checks */
57
58
assert(decoder);
59
60
ret = nvc0_decoder_bsp_next(dec, comm_seq, num_buffers, data, num_bytes);
61
62
assert(ret == 2);
63
}
64
65
static void
66
nvc0_decoder_end_frame(struct pipe_video_codec *decoder,
67
struct pipe_video_buffer *video_target,
68
struct pipe_picture_desc *picture)
69
{
70
struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder;
71
struct nouveau_vp3_video_buffer *target = (struct nouveau_vp3_video_buffer *)video_target;
72
uint32_t comm_seq = dec->fence_seq;
73
union pipe_desc desc;
74
75
unsigned vp_caps, is_ref;
76
ASSERTED unsigned ret; /* used in debug checks */
77
struct nouveau_vp3_video_buffer *refs[16] = {};
78
79
desc.base = picture;
80
81
ret = nvc0_decoder_bsp_end(dec, desc, target, comm_seq, &vp_caps, &is_ref, refs);
82
83
/* did we decode bitstream correctly? */
84
assert(ret == 2);
85
86
nvc0_decoder_vp(dec, desc, target, comm_seq, vp_caps, is_ref, refs);
87
nvc0_decoder_ppp(dec, desc, target, comm_seq);
88
}
89
90
struct pipe_video_codec *
91
nvc0_create_decoder(struct pipe_context *context,
92
const struct pipe_video_codec *templ)
93
{
94
struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base;
95
struct nouveau_vp3_decoder *dec;
96
struct nouveau_pushbuf **push;
97
union nouveau_bo_config cfg;
98
bool kepler = screen->device->chipset >= 0xe0;
99
100
cfg.nvc0.tile_mode = 0x10;
101
cfg.nvc0.memtype = 0xfe;
102
103
int ret, i;
104
uint32_t codec = 1, ppp_codec = 3;
105
uint32_t timeout;
106
u32 tmp_size = 0;
107
108
if (getenv("XVMC_VL"))
109
return vl_create_decoder(context, templ);
110
111
if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
112
debug_printf("%x\n", templ->entrypoint);
113
return NULL;
114
}
115
116
dec = CALLOC_STRUCT(nouveau_vp3_decoder);
117
if (!dec)
118
return NULL;
119
dec->client = screen->client;
120
dec->base = *templ;
121
nouveau_vp3_decoder_init_common(&dec->base);
122
123
if (!kepler) {
124
dec->bsp_idx = 5;
125
dec->vp_idx = 6;
126
dec->ppp_idx = 7;
127
} else {
128
dec->bsp_idx = 2;
129
dec->vp_idx = 2;
130
dec->ppp_idx = 2;
131
}
132
133
for (i = 0; i < 3; ++i)
134
if (i && !kepler) {
135
dec->channel[i] = dec->channel[0];
136
dec->pushbuf[i] = dec->pushbuf[0];
137
} else {
138
void *data;
139
u32 size;
140
struct nvc0_fifo nvc0_args = {};
141
struct nve0_fifo nve0_args = {};
142
143
if (!kepler) {
144
size = sizeof(nvc0_args);
145
data = &nvc0_args;
146
} else {
147
unsigned engine[] = {
148
NVE0_FIFO_ENGINE_BSP,
149
NVE0_FIFO_ENGINE_VP,
150
NVE0_FIFO_ENGINE_PPP
151
};
152
153
nve0_args.engine = engine[i];
154
size = sizeof(nve0_args);
155
data = &nve0_args;
156
}
157
158
ret = nouveau_object_new(&screen->device->object, 0,
159
NOUVEAU_FIFO_CHANNEL_CLASS,
160
data, size, &dec->channel[i]);
161
162
if (!ret)
163
ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4,
164
32 * 1024, true, &dec->pushbuf[i]);
165
if (ret)
166
break;
167
}
168
push = dec->pushbuf;
169
170
if (!kepler) {
171
if (!ret)
172
ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp);
173
if (!ret)
174
ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp);
175
if (!ret)
176
ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp);
177
} else {
178
if (!ret)
179
ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp);
180
if (!ret)
181
ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp);
182
if (!ret)
183
ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp);
184
}
185
if (ret)
186
goto fail;
187
188
BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
189
PUSH_DATA (push[0], dec->bsp->handle);
190
191
BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
192
PUSH_DATA (push[1], dec->vp->handle);
193
194
BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
195
PUSH_DATA (push[2], dec->ppp->handle);
196
197
dec->base.context = context;
198
dec->base.begin_frame = nvc0_decoder_begin_frame;
199
dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
200
dec->base.end_frame = nvc0_decoder_end_frame;
201
202
for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
203
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
204
0, 1 << 20, &cfg, &dec->bsp_bo[i]);
205
if (!ret) {
206
/* total fudge factor... just has to be bigger for higher bitrates? */
207
unsigned inter_size = align(templ->width * templ->height * 2, 4 << 20);
208
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
209
0x100, inter_size, &cfg, &dec->inter_bo[0]);
210
}
211
if (!ret) {
212
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
213
0x100, dec->inter_bo[0]->size, &cfg,
214
&dec->inter_bo[1]);
215
}
216
if (ret)
217
goto fail;
218
switch (u_reduce_video_profile(templ->profile)) {
219
case PIPE_VIDEO_FORMAT_MPEG12: {
220
codec = 1;
221
assert(templ->max_references <= 2);
222
break;
223
}
224
case PIPE_VIDEO_FORMAT_MPEG4: {
225
codec = 4;
226
tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
227
assert(templ->max_references <= 2);
228
break;
229
}
230
case PIPE_VIDEO_FORMAT_VC1: {
231
ppp_codec = codec = 2;
232
tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
233
assert(templ->max_references <= 2);
234
break;
235
}
236
case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
237
codec = 3;
238
dec->tmp_stride = 16 * mb_half(templ->width) * nouveau_vp3_video_align(templ->height) * 3 / 2;
239
tmp_size = dec->tmp_stride * (templ->max_references + 1);
240
assert(templ->max_references <= 16);
241
break;
242
}
243
default:
244
fprintf(stderr, "invalid codec\n");
245
goto fail;
246
}
247
248
if (screen->device->chipset < 0xd0) {
249
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
250
0x4000, &cfg, &dec->fw_bo);
251
if (ret)
252
goto fail;
253
254
ret = nouveau_vp3_load_firmware(dec, templ->profile, screen->device->chipset);
255
if (ret)
256
goto fw_fail;
257
}
258
259
if (codec != 3) {
260
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
261
0x400, &cfg, &dec->bitplane_bo);
262
if (ret)
263
goto fail;
264
}
265
266
dec->ref_stride = mb(templ->width)*16 * (mb_half(templ->height)*32 + nouveau_vp3_video_align(templ->height)/2);
267
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
268
dec->ref_stride * (templ->max_references+2) + tmp_size,
269
&cfg, &dec->ref_bo);
270
if (ret)
271
goto fail;
272
273
timeout = 0;
274
275
BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2);
276
PUSH_DATA (push[0], codec);
277
PUSH_DATA (push[0], timeout);
278
279
BEGIN_NVC0(push[1], SUBC_VP(0x200), 2);
280
PUSH_DATA (push[1], codec);
281
PUSH_DATA (push[1], timeout);
282
283
BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2);
284
PUSH_DATA (push[2], ppp_codec);
285
PUSH_DATA (push[2], timeout);
286
287
++dec->fence_seq;
288
289
#if NOUVEAU_VP3_DEBUG_FENCE
290
ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
291
0, 0x1000, NULL, &dec->fence_bo);
292
if (ret)
293
goto fail;
294
295
nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
296
dec->fence_map = dec->fence_bo->map;
297
dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
298
dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
299
300
/* So lets test if the fence is working? */
301
nouveau_pushbuf_space(push[0], 16, 1, 0);
302
PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
303
BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
304
PUSH_DATAh(push[0], dec->fence_bo->offset);
305
PUSH_DATA (push[0], dec->fence_bo->offset);
306
PUSH_DATA (push[0], dec->fence_seq);
307
308
BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
309
PUSH_DATA (push[0], 0);
310
PUSH_KICK (push[0]);
311
312
nouveau_pushbuf_space(push[1], 16, 1, 0);
313
PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
314
BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
315
PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
316
PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
317
PUSH_DATA (push[1], dec->fence_seq);
318
319
BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
320
PUSH_DATA (push[1], 0);
321
PUSH_KICK (push[1]);
322
323
nouveau_pushbuf_space(push[2], 16, 1, 0);
324
PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
325
BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
326
PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
327
PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
328
PUSH_DATA (push[2], dec->fence_seq);
329
330
BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
331
PUSH_DATA (push[2], 0);
332
PUSH_KICK (push[2]);
333
334
usleep(100);
335
while (dec->fence_seq > dec->fence_map[0] ||
336
dec->fence_seq > dec->fence_map[4] ||
337
dec->fence_seq > dec->fence_map[8]) {
338
debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
339
usleep(100);
340
}
341
debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
342
#endif
343
344
return &dec->base;
345
346
fw_fail:
347
debug_printf("Cannot create decoder without firmware..\n");
348
dec->base.destroy(&dec->base);
349
return NULL;
350
351
fail:
352
debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
353
dec->base.destroy(&dec->base);
354
return NULL;
355
}
356
357
struct pipe_video_buffer *
358
nvc0_video_buffer_create(struct pipe_context *pipe,
359
const struct pipe_video_buffer *templat)
360
{
361
return nouveau_vp3_video_buffer_create(
362
pipe, templat, NVC0_RESOURCE_FLAG_VIDEO);
363
}
364
365