Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 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 | #if NOUVEAU_VP3_DEBUG_FENCE |
||
26 | static void dump_comm_bsp(struct comm *comm) |
||
27 | { |
||
28 | unsigned idx = comm->bsp_cur_index & 0xf; |
||
29 | debug_printf("Cur seq: %x, bsp byte ofs: %x\n", comm->bsp_cur_index, comm->byte_ofs); |
||
30 | debug_printf("Status: %08x, pos: %08x\n", comm->status[idx], comm->pos[idx]); |
||
31 | } |
||
32 | #endif |
||
33 | |||
34 | unsigned |
||
35 | nvc0_decoder_bsp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, |
||
36 | struct nouveau_vp3_video_buffer *target, |
||
37 | unsigned comm_seq, unsigned num_buffers, |
||
38 | const void *const *data, const unsigned *num_bytes, |
||
39 | unsigned *vp_caps, unsigned *is_ref, |
||
40 | struct nouveau_vp3_video_buffer *refs[16]) |
||
41 | { |
||
42 | struct nouveau_pushbuf *push = dec->pushbuf[0]; |
||
43 | enum pipe_video_format codec = u_reduce_video_profile(dec->base.profile); |
||
44 | uint32_t bsp_addr, comm_addr, inter_addr; |
||
45 | uint32_t slice_size, bucket_size, ring_size, bsp_size; |
||
46 | uint32_t caps, i; |
||
47 | int ret; |
||
48 | struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH]; |
||
49 | struct nouveau_bo *inter_bo = dec->inter_bo[comm_seq & 1]; |
||
50 | unsigned fence_extra = 0; |
||
51 | struct nouveau_pushbuf_refn bo_refs[] = { |
||
52 | { bsp_bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM }, |
||
53 | { inter_bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM }, |
||
54 | #if NOUVEAU_VP3_DEBUG_FENCE |
||
55 | { dec->fence_bo, NOUVEAU_BO_WR | NOUVEAU_BO_GART }, |
||
56 | #endif |
||
57 | { dec->bitplane_bo, NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM }, |
||
58 | }; |
||
59 | int num_refs = sizeof(bo_refs)/sizeof(*bo_refs); |
||
60 | |||
61 | if (!dec->bitplane_bo) |
||
62 | num_refs--; |
||
63 | |||
64 | #if NOUVEAU_VP3_DEBUG_FENCE |
||
65 | fence_extra = 4; |
||
66 | #endif |
||
67 | |||
68 | bsp_size = NOUVEAU_VP3_BSP_RESERVED_SIZE; |
||
69 | for (i = 0; i < num_buffers; i++) |
||
70 | bsp_size += num_bytes[i]; |
||
71 | bsp_size += 256; /* the 4 end markers */ |
||
72 | |||
73 | if (!bsp_bo || bsp_size > bsp_bo->size) { |
||
74 | union nouveau_bo_config cfg; |
||
75 | struct nouveau_bo *tmp_bo = NULL; |
||
76 | |||
77 | cfg.nvc0.tile_mode = 0x10; |
||
78 | cfg.nvc0.memtype = 0xfe; |
||
79 | |||
80 | /* round up to the nearest mb */ |
||
81 | bsp_size += (1 << 20) - 1; |
||
82 | bsp_size &= ~((1 << 20) - 1); |
||
83 | |||
84 | ret = nouveau_bo_new(dec->bitplane_bo->device, NOUVEAU_BO_VRAM, 0, bsp_size, &cfg, &tmp_bo); |
||
85 | if (ret) { |
||
86 | debug_printf("reallocating bsp %u -> %u failed with %i\n", |
||
87 | bsp_bo ? (unsigned)bsp_bo->size : 0, bsp_size, ret); |
||
88 | return -1; |
||
89 | } |
||
90 | nouveau_bo_ref(NULL, &bsp_bo); |
||
91 | bo_refs[0].bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH] = bsp_bo = tmp_bo; |
||
92 | } |
||
93 | |||
94 | if (!inter_bo || bsp_bo->size * 4 > inter_bo->size) { |
||
95 | union nouveau_bo_config cfg; |
||
96 | struct nouveau_bo *tmp_bo = NULL; |
||
97 | |||
98 | cfg.nvc0.tile_mode = 0x10; |
||
99 | cfg.nvc0.memtype = 0xfe; |
||
100 | |||
101 | ret = nouveau_bo_new(dec->bitplane_bo->device, NOUVEAU_BO_VRAM, 0, bsp_bo->size * 4, &cfg, &tmp_bo); |
||
102 | if (ret) { |
||
103 | debug_printf("reallocating inter %u -> %u failed with %i\n", |
||
104 | inter_bo ? (unsigned)inter_bo->size : 0, (unsigned)bsp_bo->size * 4, ret); |
||
105 | return -1; |
||
106 | } |
||
107 | nouveau_bo_ref(NULL, &inter_bo); |
||
108 | bo_refs[1].bo = dec->inter_bo[comm_seq & 1] = inter_bo = tmp_bo; |
||
109 | } |
||
110 | |||
111 | ret = nouveau_bo_map(bsp_bo, NOUVEAU_BO_WR, dec->client); |
||
112 | if (ret) { |
||
113 | debug_printf("map failed: %i %s\n", ret, strerror(-ret)); |
||
114 | return -1; |
||
115 | } |
||
116 | |||
117 | caps = nouveau_vp3_bsp(dec, desc, target, comm_seq, |
||
118 | num_buffers, data, num_bytes); |
||
119 | |||
120 | nouveau_vp3_vp_caps(dec, desc, target, comm_seq, vp_caps, is_ref, refs); |
||
121 | |||
122 | nouveau_pushbuf_space(push, 6 + (codec == PIPE_VIDEO_FORMAT_MPEG4_AVC ? 9 : 7) + fence_extra + 2, num_refs, 0); |
||
123 | nouveau_pushbuf_refn(push, bo_refs, num_refs); |
||
124 | |||
125 | bsp_addr = bsp_bo->offset >> 8; |
||
126 | inter_addr = inter_bo->offset >> 8; |
||
127 | |||
128 | #if NOUVEAU_VP3_DEBUG_FENCE |
||
129 | memset(dec->comm, 0, 0x200); |
||
130 | comm_addr = (dec->fence_bo->offset + COMM_OFFSET) >> 8; |
||
131 | #else |
||
132 | comm_addr = bsp_addr + (COMM_OFFSET>>8); |
||
133 | #endif |
||
134 | |||
135 | BEGIN_NVC0(push, SUBC_BSP(0x700), 5); |
||
136 | PUSH_DATA (push, caps); // 700 cmd |
||
137 | PUSH_DATA (push, bsp_addr + 1); // 704 strparm_bsp |
||
138 | PUSH_DATA (push, bsp_addr + 7); // 708 str addr |
||
139 | PUSH_DATA (push, comm_addr); // 70c comm |
||
140 | PUSH_DATA (push, comm_seq); // 710 seq |
||
141 | |||
142 | if (codec != PIPE_VIDEO_FORMAT_MPEG4_AVC) { |
||
143 | u32 bitplane_addr; |
||
144 | |||
145 | bitplane_addr = dec->bitplane_bo->offset >> 8; |
||
146 | |||
147 | nouveau_vp3_inter_sizes(dec, 1, &slice_size, &bucket_size, &ring_size); |
||
148 | BEGIN_NVC0(push, SUBC_BSP(0x400), 6); |
||
149 | PUSH_DATA (push, bsp_addr); // 400 picparm addr |
||
150 | PUSH_DATA (push, inter_addr); // 404 interparm addr |
||
151 | PUSH_DATA (push, inter_addr + slice_size + bucket_size); // 408 interdata addr |
||
152 | PUSH_DATA (push, ring_size << 8); // 40c interdata_size |
||
153 | PUSH_DATA (push, bitplane_addr); // 410 BITPLANE_DATA |
||
154 | PUSH_DATA (push, 0x400); // 414 BITPLANE_DATA_SIZE |
||
155 | } else { |
||
156 | nouveau_vp3_inter_sizes(dec, desc.h264->slice_count, &slice_size, &bucket_size, &ring_size); |
||
157 | BEGIN_NVC0(push, SUBC_BSP(0x400), 8); |
||
158 | PUSH_DATA (push, bsp_addr); // 400 picparm addr |
||
159 | PUSH_DATA (push, inter_addr); // 404 interparm addr |
||
160 | PUSH_DATA (push, slice_size << 8); // 408 interparm size? |
||
161 | PUSH_DATA (push, inter_addr + slice_size + bucket_size); // 40c interdata addr |
||
162 | PUSH_DATA (push, ring_size << 8); // 410 interdata size |
||
163 | PUSH_DATA (push, inter_addr + slice_size); // 414 bucket? |
||
164 | PUSH_DATA (push, bucket_size << 8); // 418 bucket size? unshifted.. |
||
165 | PUSH_DATA (push, 0); // 41c targets |
||
166 | // TODO: Double check 414 / 418 with nvidia trace |
||
167 | } |
||
168 | |||
169 | #if NOUVEAU_VP3_DEBUG_FENCE |
||
170 | BEGIN_NVC0(push, SUBC_BSP(0x240), 3); |
||
171 | PUSH_DATAh(push, dec->fence_bo->offset); |
||
172 | PUSH_DATA (push, dec->fence_bo->offset); |
||
173 | PUSH_DATA (push, dec->fence_seq); |
||
174 | |||
175 | BEGIN_NVC0(push, SUBC_BSP(0x300), 1); |
||
176 | PUSH_DATA (push, 1); |
||
177 | PUSH_KICK (push); |
||
178 | |||
179 | { |
||
180 | unsigned spin = 0; |
||
181 | do { |
||
182 | usleep(100); |
||
183 | if ((spin++ & 0xff) == 0xff) { |
||
184 | debug_printf("b%u: %u\n", dec->fence_seq, dec->fence_map[0]); |
||
185 | dump_comm_bsp(dec->comm); |
||
186 | } |
||
187 | } while (dec->fence_seq > dec->fence_map[0]); |
||
188 | } |
||
189 | |||
190 | dump_comm_bsp(dec->comm); |
||
191 | return dec->comm->status[comm_seq & 0xf]; |
||
192 | #else |
||
193 | BEGIN_NVC0(push, SUBC_BSP(0x300), 1); |
||
194 | PUSH_DATA (push, 0); |
||
195 | PUSH_KICK (push); |
||
196 | return 2; |
||
197 | #endif |
||
198 | }><>><>><>><>><>><>> |