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_vp.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
#include <sys/mman.h>
25
26
#if NOUVEAU_VP3_DEBUG_FENCE
27
static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32 comm_seq,
28
struct nouveau_bo *inter_bo, unsigned slice_size)
29
{
30
unsigned i, idx = comm->pvp_cur_index & 0xf;
31
debug_printf("Status: %08x, stage: %08x\n", comm->status_vp[idx], comm->pvp_stage);
32
#if 0
33
debug_printf("Acked byte ofs: %x, bsp byte ofs: %x\n", comm->acked_byte_ofs, comm->byte_ofs);
34
debug_printf("Irq/parse indexes: %i %i\n", comm->irq_index, comm->parse_endpos_index);
35
36
for (i = 0; i != comm->irq_index; ++i)
37
debug_printf("irq[%i] = { @ %08x -> %04x }\n", i, comm->irq_pos[i], comm->irq_470[i]);
38
for (i = 0; i != comm->parse_endpos_index; ++i)
39
debug_printf("parse_endpos[%i] = { @ %08x}\n", i, comm->parse_endpos[i]);
40
#endif
41
debug_printf("mb_y = %u\n", comm->mb_y[idx]);
42
if (comm->status_vp[idx] <= 1)
43
return;
44
45
if ((comm->pvp_stage & 0xff) != 0xff) {
46
unsigned *map;
47
int ret = nouveau_bo_map(inter_bo, NOUVEAU_BO_RD|NOUVEAU_BO_NOBLOCK, dec->client);
48
assert(ret >= 0);
49
map = inter_bo->map;
50
for (i = 0; i < comm->byte_ofs + slice_size; i += 0x10) {
51
debug_printf("%05x: %08x %08x %08x %08x\n", i, map[i/4], map[i/4+1], map[i/4+2], map[i/4+3]);
52
}
53
munmap(inter_bo->map, inter_bo->size);
54
inter_bo->map = NULL;
55
}
56
assert((comm->pvp_stage & 0xff) == 0xff);
57
}
58
#endif
59
60
static void
61
nvc0_decoder_kick_ref(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video_buffer *target)
62
{
63
dec->refs[target->valid_ref].last_used = 0;
64
// debug_printf("Unreffed %p\n", target);
65
}
66
67
void
68
nvc0_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc,
69
struct nouveau_vp3_video_buffer *target, unsigned comm_seq,
70
unsigned caps, unsigned is_ref,
71
struct nouveau_vp3_video_buffer *refs[16])
72
{
73
struct nouveau_pushbuf *push = dec->pushbuf[1];
74
uint32_t bsp_addr, comm_addr, inter_addr, ucode_addr, pic_addr[17], last_addr, null_addr;
75
uint32_t slice_size, bucket_size, ring_size, i;
76
enum pipe_video_format codec = u_reduce_video_profile(dec->base.profile);
77
struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH];
78
struct nouveau_bo *inter_bo = dec->inter_bo[comm_seq & 1];
79
u32 codec_extra = 0;
80
struct nouveau_pushbuf_refn bo_refs[] = {
81
{ inter_bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM },
82
{ dec->ref_bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM },
83
{ bsp_bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM },
84
#if NOUVEAU_VP3_DEBUG_FENCE
85
{ dec->fence_bo, NOUVEAU_BO_WR | NOUVEAU_BO_GART },
86
#endif
87
{ dec->fw_bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM },
88
};
89
int num_refs = ARRAY_SIZE(bo_refs) - !dec->fw_bo;
90
91
if (codec == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
92
nouveau_vp3_inter_sizes(dec, desc.h264->slice_count, &slice_size, &bucket_size, &ring_size);
93
codec_extra += 2;
94
} else
95
nouveau_vp3_inter_sizes(dec, 1, &slice_size, &bucket_size, &ring_size);
96
97
if (dec->base.max_references > 2)
98
codec_extra += 1 + (dec->base.max_references - 2);
99
100
pic_addr[16] = nouveau_vp3_video_addr(dec, target) >> 8;
101
last_addr = null_addr = nouveau_vp3_video_addr(dec, NULL) >> 8;
102
103
for (i = 0; i < dec->base.max_references; ++i) {
104
if (!refs[i])
105
pic_addr[i] = last_addr;
106
else if (dec->refs[refs[i]->valid_ref].vidbuf == refs[i])
107
last_addr = pic_addr[i] = nouveau_vp3_video_addr(dec, refs[i]) >> 8;
108
else
109
pic_addr[i] = null_addr;
110
}
111
if (!is_ref && (dec->refs[target->valid_ref].decoded_top && dec->refs[target->valid_ref].decoded_bottom))
112
nvc0_decoder_kick_ref(dec, target);
113
114
nouveau_pushbuf_space(push, 32 + codec_extra, num_refs, 0);
115
116
nouveau_pushbuf_refn(push, bo_refs, num_refs);
117
118
bsp_addr = bsp_bo->offset >> 8;
119
#if NOUVEAU_VP3_DEBUG_FENCE
120
comm_addr = (dec->fence_bo->offset + COMM_OFFSET)>>8;
121
#else
122
comm_addr = bsp_addr + (COMM_OFFSET>>8);
123
#endif
124
inter_addr = inter_bo->offset >> 8;
125
if (dec->fw_bo)
126
ucode_addr = dec->fw_bo->offset >> 8;
127
else
128
ucode_addr = 0;
129
130
BEGIN_NVC0(push, SUBC_VP(0x700), 7);
131
PUSH_DATA (push, caps); // 700
132
PUSH_DATA (push, comm_seq); // 704
133
PUSH_DATA (push, 0); // 708 fuc targets, ignored for nvc0
134
PUSH_DATA (push, dec->fw_sizes); // 70c
135
PUSH_DATA (push, bsp_addr+(VP_OFFSET>>8)); // 710 picparm_addr
136
PUSH_DATA (push, inter_addr); // 714 inter_parm
137
PUSH_DATA (push, inter_addr + slice_size + bucket_size); // 718 inter_data_ofs
138
139
if (bucket_size) {
140
uint64_t tmpimg_addr = dec->ref_bo->offset + dec->ref_stride * (dec->base.max_references+2);
141
142
BEGIN_NVC0(push, SUBC_VP(0x71c), 2);
143
PUSH_DATA (push, tmpimg_addr >> 8); // 71c
144
PUSH_DATA (push, inter_addr + slice_size); // 720 bucket_ofs
145
}
146
147
BEGIN_NVC0(push, SUBC_VP(0x724), 5);
148
PUSH_DATA (push, comm_addr); // 724
149
PUSH_DATA (push, ucode_addr); // 728
150
PUSH_DATA (push, pic_addr[16]); // 734
151
PUSH_DATA (push, pic_addr[0]); // 72c
152
PUSH_DATA (push, pic_addr[1]); // 730
153
154
if (dec->base.max_references > 2) {
155
int i;
156
157
BEGIN_NVC0(push, SUBC_VP(0x400), dec->base.max_references - 2);
158
for (i = 2; i < dec->base.max_references; ++i) {
159
assert(0x400 + (i - 2) * 4 < 0x438);
160
PUSH_DATA (push, pic_addr[i]);
161
}
162
}
163
164
if (codec == PIPE_VIDEO_FORMAT_MPEG4_AVC) {
165
BEGIN_NVC0(push, SUBC_VP(0x438), 1);
166
PUSH_DATA (push, desc.h264->slice_count);
167
}
168
169
//debug_printf("Decoding %08lx with %08lx and %08lx\n", pic_addr[16], pic_addr[0], pic_addr[1]);
170
171
#if NOUVEAU_VP3_DEBUG_FENCE
172
BEGIN_NVC0(push, SUBC_VP(0x240), 3);
173
PUSH_DATAh(push, (dec->fence_bo->offset + 0x10));
174
PUSH_DATA (push, (dec->fence_bo->offset + 0x10));
175
PUSH_DATA (push, dec->fence_seq);
176
177
BEGIN_NVC0(push, SUBC_VP(0x300), 1);
178
PUSH_DATA (push, 1);
179
PUSH_KICK(push);
180
181
{
182
unsigned spin = 0;
183
do {
184
usleep(100);
185
if ((spin++ & 0xff) == 0xff) {
186
debug_printf("v%u: %u\n", dec->fence_seq, dec->fence_map[4]);
187
dump_comm_vp(dec, dec->comm, comm_seq, inter_bo, slice_size << 8);
188
}
189
} while (dec->fence_seq > dec->fence_map[4]);
190
}
191
dump_comm_vp(dec, dec->comm, comm_seq, inter_bo, slice_size << 8);
192
#else
193
BEGIN_NVC0(push, SUBC_VP(0x300), 1);
194
PUSH_DATA (push, 0);
195
PUSH_KICK (push);
196
#endif
197
}
198
199