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