• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
nvc0_decoder_begin_frame(struct pipe_video_codec * decoder,struct pipe_video_buffer * target,struct pipe_picture_desc * picture)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
nvc0_decoder_decode_bitstream(struct pipe_video_codec * decoder,struct pipe_video_buffer * video_target,struct pipe_picture_desc * picture,unsigned num_buffers,const void * const * data,const unsigned * num_bytes)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
nvc0_decoder_end_frame(struct pipe_video_codec * decoder,struct pipe_video_buffer * video_target,struct pipe_picture_desc * picture)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 *
nvc0_create_decoder(struct pipe_context * context,const struct pipe_video_codec * templ)91 nvc0_create_decoder(struct pipe_context *context,
92                     const struct pipe_video_codec *templ)
93 {
94    struct nvc0_context *nvc0 = nvc0_context(context);
95    struct nouveau_screen *screen = &nvc0->screen->base;
96    struct nouveau_vp3_decoder *dec;
97    struct nouveau_pushbuf **push;
98    union nouveau_bo_config cfg;
99    bool kepler = screen->device->chipset >= 0xe0;
100 
101    cfg.nvc0.tile_mode = 0x10;
102    cfg.nvc0.memtype = 0xfe;
103 
104    int ret, i;
105    uint32_t codec = 1, ppp_codec = 3;
106    uint32_t timeout;
107    u32 tmp_size = 0;
108 
109    if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
110       debug_printf("%x\n", templ->entrypoint);
111       return NULL;
112    }
113 
114    dec = CALLOC_STRUCT(nouveau_vp3_decoder);
115    if (!dec)
116       return NULL;
117    dec->client = nvc0->base.client;
118    dec->base = *templ;
119    nouveau_vp3_decoder_init_common(&dec->base);
120 
121    if (!kepler) {
122       dec->bsp_idx = 5;
123       dec->vp_idx = 6;
124       dec->ppp_idx = 7;
125    } else {
126       dec->bsp_idx = 2;
127       dec->vp_idx = 2;
128       dec->ppp_idx = 2;
129    }
130 
131    for (i = 0; i < 3; ++i)
132       if (i && !kepler) {
133          dec->channel[i] = dec->channel[0];
134          dec->pushbuf[i] = dec->pushbuf[0];
135       } else {
136          void *data;
137          u32 size;
138          struct nvc0_fifo nvc0_args = {};
139          struct nve0_fifo nve0_args = {};
140 
141          if (!kepler) {
142             size = sizeof(nvc0_args);
143             data = &nvc0_args;
144          } else {
145             unsigned engine[] = {
146                NVE0_FIFO_ENGINE_BSP,
147                NVE0_FIFO_ENGINE_VP,
148                NVE0_FIFO_ENGINE_PPP
149             };
150 
151             nve0_args.engine = engine[i];
152             size = sizeof(nve0_args);
153             data = &nve0_args;
154          }
155 
156          ret = nouveau_object_new(&screen->device->object, 0,
157                                   NOUVEAU_FIFO_CHANNEL_CLASS,
158                                   data, size, &dec->channel[i]);
159 
160          if (!ret)
161             ret = nouveau_pushbuf_create(screen, &nvc0->base, nvc0->base.client, dec->channel[i],
162                                          4, 32 * 1024, true, &dec->pushbuf[i]);
163          if (ret)
164             break;
165       }
166    push = dec->pushbuf;
167 
168    if (!kepler) {
169       if (!ret)
170          ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp);
171       if (!ret)
172          ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp);
173       if (!ret)
174          ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp);
175    } else {
176       if (!ret)
177          ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp);
178       if (!ret)
179          ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp);
180       if (!ret)
181          ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp);
182    }
183    if (ret)
184       goto fail;
185 
186    BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
187    PUSH_DATA (push[0], dec->bsp->handle);
188 
189    BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
190    PUSH_DATA (push[1], dec->vp->handle);
191 
192    BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
193    PUSH_DATA (push[2], dec->ppp->handle);
194 
195    dec->base.context = context;
196    dec->base.begin_frame = nvc0_decoder_begin_frame;
197    dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
198    dec->base.end_frame = nvc0_decoder_end_frame;
199 
200    for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
201       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
202                            0, 1 << 20, &cfg, &dec->bsp_bo[i]);
203    if (!ret) {
204       /* total fudge factor... just has to be bigger for higher bitrates? */
205       unsigned inter_size = align(templ->width * templ->height * 2, 4 << 20);
206       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
207                            0x100, inter_size, &cfg, &dec->inter_bo[0]);
208    }
209    if (!ret) {
210       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
211                            0x100, dec->inter_bo[0]->size, &cfg,
212                            &dec->inter_bo[1]);
213    }
214    if (ret)
215       goto fail;
216    switch (u_reduce_video_profile(templ->profile)) {
217    case PIPE_VIDEO_FORMAT_MPEG12: {
218       codec = 1;
219       assert(templ->max_references <= 2);
220       break;
221    }
222    case PIPE_VIDEO_FORMAT_MPEG4: {
223       codec = 4;
224       tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
225       assert(templ->max_references <= 2);
226       break;
227    }
228    case PIPE_VIDEO_FORMAT_VC1: {
229       ppp_codec = codec = 2;
230       tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
231       assert(templ->max_references <= 2);
232       break;
233    }
234    case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
235       codec = 3;
236       dec->tmp_stride = 16 * mb_half(templ->width) * nouveau_vp3_video_align(templ->height) * 3 / 2;
237       tmp_size = dec->tmp_stride * (templ->max_references + 1);
238       assert(templ->max_references <= 16);
239       break;
240    }
241    default:
242       fprintf(stderr, "invalid codec\n");
243       goto fail;
244    }
245 
246    if (screen->device->chipset < 0xd0) {
247       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
248                            0x4000, &cfg, &dec->fw_bo);
249       if (ret)
250          goto fail;
251 
252       ret = nouveau_vp3_load_firmware(dec, templ->profile, screen->device->chipset);
253       if (ret)
254          goto fw_fail;
255    }
256 
257    if (codec != 3) {
258       ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
259                            0x400, &cfg, &dec->bitplane_bo);
260       if (ret)
261          goto fail;
262    }
263 
264    dec->ref_stride = mb(templ->width)*16 * (mb_half(templ->height)*32 + nouveau_vp3_video_align(templ->height)/2);
265    ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
266                         dec->ref_stride * (templ->max_references+2) + tmp_size,
267                         &cfg, &dec->ref_bo);
268    if (ret)
269       goto fail;
270 
271    timeout = 0;
272 
273    BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2);
274    PUSH_DATA (push[0], codec);
275    PUSH_DATA (push[0], timeout);
276 
277    BEGIN_NVC0(push[1], SUBC_VP(0x200), 2);
278    PUSH_DATA (push[1], codec);
279    PUSH_DATA (push[1], timeout);
280 
281    BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2);
282    PUSH_DATA (push[2], ppp_codec);
283    PUSH_DATA (push[2], timeout);
284 
285    ++dec->fence_seq;
286 
287 #if NOUVEAU_VP3_DEBUG_FENCE
288    ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
289                         0, 0x1000, NULL, &dec->fence_bo);
290    if (ret)
291       goto fail;
292 
293    BO_MAP(screen, dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
294    dec->fence_map = dec->fence_bo->map;
295    dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
296    dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));
297 
298    /* So lets test if the fence is working? */
299    PUSH_SPACE_EX(push[0], 16, 1, 0);
300    PUSH_REF1 (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
301    BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
302    PUSH_DATAh(push[0], dec->fence_bo->offset);
303    PUSH_DATA (push[0], dec->fence_bo->offset);
304    PUSH_DATA (push[0], dec->fence_seq);
305 
306    BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
307    PUSH_DATA (push[0], 0);
308    PUSH_KICK (push[0]);
309 
310    PUSH_SPACE_EX(push[1], 16, 1, 0);
311    PUSH_REF1 (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
312    BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
313    PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
314    PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
315    PUSH_DATA (push[1], dec->fence_seq);
316 
317    BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
318    PUSH_DATA (push[1], 0);
319    PUSH_KICK (push[1]);
320 
321    PUSH_SPACE_EX(push[2], 16, 1, 0);
322    PUSH_REF1 (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
323    BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
324    PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
325    PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
326    PUSH_DATA (push[2], dec->fence_seq);
327 
328    BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
329    PUSH_DATA (push[2], 0);
330    PUSH_KICK (push[2]);
331 
332    usleep(100);
333    while (dec->fence_seq > dec->fence_map[0] ||
334           dec->fence_seq > dec->fence_map[4] ||
335           dec->fence_seq > dec->fence_map[8]) {
336       debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
337       usleep(100);
338    }
339    debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
340 #endif
341 
342    return &dec->base;
343 
344 fw_fail:
345    debug_printf("Cannot create decoder without firmware..\n");
346    dec->base.destroy(&dec->base);
347    return NULL;
348 
349 fail:
350    debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
351    dec->base.destroy(&dec->base);
352    return NULL;
353 }
354 
355 struct pipe_video_buffer *
nvc0_video_buffer_create(struct pipe_context * pipe,const struct pipe_video_buffer * templat)356 nvc0_video_buffer_create(struct pipe_context *pipe,
357                          const struct pipe_video_buffer *templat)
358 {
359    return nouveau_vp3_video_buffer_create(
360          pipe, templat, NVC0_RESOURCE_FLAG_VIDEO);
361 }
362