Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 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_video.h"
24
 
25
struct strparm_bsp {
26
	uint32_t w0[4]; // bits 0-23 length, bits 24-31 addr_hi
27
	uint32_t w1[4]; // bit 8-24 addr_lo
28
	uint32_t unk20; // should be idx * 0x8000000, bitstream offset
29
	uint32_t do_crypto_crap; // set to 0
30
};
31
 
32
struct mpeg12_picparm_bsp {
33
	uint16_t width;
34
	uint16_t height;
35
	uint8_t picture_structure;
36
	uint8_t picture_coding_type;
37
	uint8_t intra_dc_precision;
38
	uint8_t frame_pred_frame_dct;
39
	uint8_t concealment_motion_vectors;
40
	uint8_t intra_vlc_format;
41
	uint16_t pad;
42
	uint8_t f_code[2][2];
43
};
44
 
45
struct mpeg4_picparm_bsp {
46
	uint16_t width;
47
	uint16_t height;
48
	uint8_t vop_time_increment_size;
49
	uint8_t interlaced;
50
	uint8_t resync_marker_disable;
51
};
52
 
53
struct vc1_picparm_bsp {
54
	uint16_t width;
55
	uint16_t height;
56
	uint8_t profile; // 04 0 simple, 1 main, 2 advanced
57
	uint8_t postprocflag; // 05
58
	uint8_t pulldown; // 06
59
	uint8_t interlaced; // 07
60
	uint8_t tfcntrflag; // 08
61
	uint8_t finterpflag; // 09
62
	uint8_t psf; // 0a
63
	uint8_t pad; // 0b
64
	uint8_t multires; // 0c
65
	uint8_t syncmarker; // 0d
66
	uint8_t rangered; // 0e
67
	uint8_t maxbframes; // 0f
68
	uint8_t dquant; // 10
69
	uint8_t panscan_flag; // 11
70
	uint8_t refdist_flag; // 12
71
	uint8_t quantizer; // 13
72
	uint8_t extended_mv; // 14
73
	uint8_t extended_dmv; // 15
74
	uint8_t overlap; // 16
75
	uint8_t vstransform; // 17
76
};
77
 
78
struct h264_picparm_bsp {
79
	// 00
80
	uint32_t unk00;
81
	// 04
82
	uint32_t log2_max_frame_num_minus4; // 04 checked
83
	uint32_t pic_order_cnt_type; // 08 checked
84
	uint32_t log2_max_pic_order_cnt_lsb_minus4; // 0c checked
85
	uint32_t delta_pic_order_always_zero_flag; // 10, or unknown
86
 
87
	uint32_t frame_mbs_only_flag; // 14, always 1?
88
	uint32_t direct_8x8_inference_flag; // 18, always 1?
89
	uint32_t width_mb; // 1c checked
90
	uint32_t height_mb; // 20 checked
91
	// 24
92
	//struct picparm2
93
		uint32_t entropy_coding_mode_flag; // 00, checked
94
		uint32_t pic_order_present_flag; // 04 checked
95
		uint32_t unk; // 08 seems to be 0?
96
		uint32_t pad1; // 0c seems to be 0?
97
		uint32_t pad2; // 10 always 0 ?
98
		uint32_t num_ref_idx_l0_active_minus1; // 14 always 0?
99
		uint32_t num_ref_idx_l1_active_minus1; // 18 always 0?
100
		uint32_t weighted_pred_flag; // 1c checked
101
		uint32_t weighted_bipred_idc; // 20 checked
102
		uint32_t pic_init_qp_minus26; // 24 checked
103
		uint32_t deblocking_filter_control_present_flag; // 28 always 1?
104
		uint32_t redundant_pic_cnt_present_flag; // 2c always 0?
105
		uint32_t transform_8x8_mode_flag; // 30 checked
106
		uint32_t mb_adaptive_frame_field_flag; // 34 checked-ish
107
		uint8_t field_pic_flag; // 38 checked
108
		uint8_t bottom_field_flag; // 39 checked
109
		uint8_t real_pad[0x1b]; // XX why?
110
};
111
 
112
static uint32_t
113
nvc0_decoder_fill_picparm_mpeg12_bsp(struct nvc0_decoder *dec,
114
                                     struct pipe_mpeg12_picture_desc *desc,
115
                                     char *map)
116
{
117
   struct mpeg12_picparm_bsp *pic_bsp = (struct mpeg12_picparm_bsp *)map;
118
   int i;
119
   pic_bsp->width = dec->base.width;
120
   pic_bsp->height = dec->base.height;
121
   pic_bsp->picture_structure = desc->picture_structure;
122
   pic_bsp->picture_coding_type = desc->picture_coding_type;
123
   pic_bsp->intra_dc_precision = desc->intra_dc_precision;
124
   pic_bsp->frame_pred_frame_dct = desc->frame_pred_frame_dct;
125
   pic_bsp->concealment_motion_vectors = desc->concealment_motion_vectors;
126
   pic_bsp->intra_vlc_format = desc->intra_vlc_format;
127
   pic_bsp->pad = 0;
128
   for (i = 0; i < 4; ++i)
129
      pic_bsp->f_code[i/2][i%2] = desc->f_code[i/2][i%2] + 1; // FU
130
 
131
   return (desc->num_slices << 4) | (dec->base.profile != PIPE_VIDEO_PROFILE_MPEG1);
132
}
133
 
134
static uint32_t
135
nvc0_decoder_fill_picparm_mpeg4_bsp(struct nvc0_decoder *dec,
136
                                    struct pipe_mpeg4_picture_desc *desc,
137
                                    char *map)
138
{
139
   struct mpeg4_picparm_bsp *pic_bsp = (struct mpeg4_picparm_bsp *)map;
140
   uint32_t t, bits = 0;
141
   pic_bsp->width = dec->base.width;
142
   pic_bsp->height = dec->base.height;
143
   assert(desc->vop_time_increment_resolution > 0);
144
 
145
   t = desc->vop_time_increment_resolution - 1;
146
   while (t) {
147
      bits++;
148
      t /= 2;
149
   }
150
   if (!bits)
151
      bits = 1;
152
   t = desc->vop_time_increment_resolution - 1;
153
   pic_bsp->vop_time_increment_size = bits;
154
   pic_bsp->interlaced = desc->interlaced;
155
   pic_bsp->resync_marker_disable = desc->resync_marker_disable;
156
   return 4;
157
}
158
 
159
static uint32_t
160
nvc0_decoder_fill_picparm_vc1_bsp(struct nvc0_decoder *dec,
161
                                  struct pipe_vc1_picture_desc *d,
162
                                  char *map)
163
{
164
   struct vc1_picparm_bsp *vc = (struct vc1_picparm_bsp *)map;
165
   uint32_t caps = (d->slice_count << 4)&0xfff0;
166
   vc->width = dec->base.width;
167
   vc->height = dec->base.height;
168
   vc->profile = dec->base.profile - PIPE_VIDEO_PROFILE_VC1_SIMPLE; // 04
169
   vc->postprocflag = d->postprocflag;
170
   vc->pulldown = d->pulldown;
171
   vc->interlaced = d->interlace;
172
   vc->tfcntrflag = d->tfcntrflag; // 08
173
   vc->finterpflag = d->finterpflag;
174
   vc->psf = d->psf;
175
   vc->pad = 0;
176
   vc->multires = d->multires; // 0c
177
   vc->syncmarker = d->syncmarker;
178
   vc->rangered = d->rangered;
179
   vc->maxbframes = d->maxbframes;
180
   vc->dquant = d->dquant; // 10
181
   vc->panscan_flag = d->panscan_flag;
182
   vc->refdist_flag = d->refdist_flag;
183
   vc->quantizer = d->quantizer;
184
   vc->extended_mv = d->extended_mv; // 14
185
   vc->extended_dmv = d->extended_dmv;
186
   vc->overlap = d->overlap;
187
   vc->vstransform = d->vstransform;
188
   return caps | 2;
189
}
190
 
191
static uint32_t
192
nvc0_decoder_fill_picparm_h264_bsp(struct nvc0_decoder *dec,
193
                                   struct pipe_h264_picture_desc *d,
194
                                   char *map)
195
{
196
   struct h264_picparm_bsp stub_h = {}, *h = &stub_h;
197
   uint32_t caps = (d->slice_count << 4)&0xfff0;
198
 
199
   assert(!(d->slice_count & ~0xfff));
200
   if (d->slice_count & 0x1000)
201
      caps |= 1 << 20;
202
 
203
   assert(offsetof(struct h264_picparm_bsp, bottom_field_flag) == (0x39 + 0x24));
204
   h->unk00 = 1;
205
   h->pad1 = h->pad2 = 0;
206
   h->unk = 0;
207
   h->log2_max_frame_num_minus4 = d->log2_max_frame_num_minus4;
208
   h->frame_mbs_only_flag = d->frame_mbs_only_flag;
209
   h->direct_8x8_inference_flag = d->direct_8x8_inference_flag;
210
   h->width_mb = mb(dec->base.width);
211
   h->height_mb = mb(dec->base.height);
212
   h->entropy_coding_mode_flag = d->entropy_coding_mode_flag;
213
   h->pic_order_present_flag = d->pic_order_present_flag;
214
   h->pic_order_cnt_type = d->pic_order_cnt_type;
215
   h->log2_max_pic_order_cnt_lsb_minus4 = d->log2_max_pic_order_cnt_lsb_minus4;
216
   h->delta_pic_order_always_zero_flag = d->delta_pic_order_always_zero_flag;
217
   h->num_ref_idx_l0_active_minus1 = d->num_ref_idx_l0_active_minus1;
218
   h->num_ref_idx_l1_active_minus1 = d->num_ref_idx_l1_active_minus1;
219
   h->weighted_pred_flag = d->weighted_pred_flag;
220
   h->weighted_bipred_idc = d->weighted_bipred_idc;
221
   h->pic_init_qp_minus26 = d->pic_init_qp_minus26;
222
   h->deblocking_filter_control_present_flag = d->deblocking_filter_control_present_flag;
223
   h->redundant_pic_cnt_present_flag = d->redundant_pic_cnt_present_flag;
224
   h->transform_8x8_mode_flag = d->transform_8x8_mode_flag;
225
   h->mb_adaptive_frame_field_flag = d->mb_adaptive_frame_field_flag;
226
   h->field_pic_flag = d->field_pic_flag;
227
   h->bottom_field_flag = d->bottom_field_flag;
228
   memset(h->real_pad, 0, sizeof(h->real_pad));
229
   *(struct h264_picparm_bsp *)map = *h;
230
   return caps | 3;
231
}
232
 
233
#if NVC0_DEBUG_FENCE
234
static void dump_comm_bsp(struct comm *comm)
235
{
236
   unsigned idx = comm->bsp_cur_index & 0xf;
237
   debug_printf("Cur seq: %x, bsp byte ofs: %x\n", comm->bsp_cur_index, comm->byte_ofs);
238
   debug_printf("Status: %08x, pos: %08x\n", comm->status[idx], comm->pos[idx]);
239
}
240
#endif
241
 
242
unsigned
243
nvc0_decoder_bsp(struct nvc0_decoder *dec, union pipe_desc desc,
244
                 struct nvc0_video_buffer *target,
245
                 unsigned comm_seq, unsigned num_buffers,
246
                 const void *const *data, const unsigned *num_bytes,
247
                 unsigned *vp_caps, unsigned *is_ref,
248
                 struct nvc0_video_buffer *refs[16])
249
{
250
   struct nouveau_pushbuf *push = dec->pushbuf[0];
251
   enum pipe_video_codec codec = u_reduce_video_profile(dec->base.profile);
252
   char *bsp;
253
   uint32_t bsp_addr, comm_addr, inter_addr;
254
   uint32_t slice_size, bucket_size, ring_size;
255
   uint32_t endmarker, caps;
256
   struct strparm_bsp *str_bsp;
257
   int ret, i;
258
   struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NVC0_VIDEO_QDEPTH];
259
   struct nouveau_bo *inter_bo = dec->inter_bo[comm_seq & 1];
260
   unsigned fence_extra = 0;
261
   struct nouveau_pushbuf_refn bo_refs[] = {
262
      { bsp_bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM },
263
      { inter_bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM },
264
#ifdef NVC0_DEBUG_FENCE
265
      { dec->fence_bo, NOUVEAU_BO_WR | NOUVEAU_BO_GART },
266
#endif
267
      { dec->bitplane_bo, NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM },
268
   };
269
   int num_refs = sizeof(bo_refs)/sizeof(*bo_refs);
270
 
271
   if (!dec->bitplane_bo)
272
      num_refs--;
273
 
274
#ifdef NVC0_DEBUG_FENCE
275
   fence_extra = 4;
276
#endif
277
 
278
   ret = nouveau_bo_map(bsp_bo, NOUVEAU_BO_WR, dec->client);
279
   if (ret) {
280
      debug_printf("map failed: %i %s\n", ret, strerror(-ret));
281
      return -1;
282
   }
283
   bsp = bsp_bo->map;
284
   /*
285
    * 0x000..0x100: picparm_bsp
286
    * 0x200..0x500: picparm_vp
287
    * 0x500..0x700: comm
288
    * 0x700..onward: raw bitstream
289
    */
290
 
291
   switch (codec){
292
   case PIPE_VIDEO_CODEC_MPEG12:
293
      endmarker = 0xb7010000;
294
      caps = nvc0_decoder_fill_picparm_mpeg12_bsp(dec, desc.mpeg12, bsp);
295
      break;
296
   case PIPE_VIDEO_CODEC_MPEG4:
297
      endmarker = 0xb1010000;
298
      caps = nvc0_decoder_fill_picparm_mpeg4_bsp(dec, desc.mpeg4, bsp);
299
      break;
300
   case PIPE_VIDEO_CODEC_VC1: {
301
      endmarker = 0x0a010000;
302
      caps = nvc0_decoder_fill_picparm_vc1_bsp(dec, desc.vc1, bsp);
303
      break;
304
   }
305
   case PIPE_VIDEO_CODEC_MPEG4_AVC: {
306
      endmarker = 0x0b010000;
307
      caps = nvc0_decoder_fill_picparm_h264_bsp(dec, desc.h264, bsp);
308
      break;
309
   }
310
   default: assert(0); return -1;
311
   }
312
 
313
   nvc0_decoder_vp_caps(dec, desc, target, comm_seq, vp_caps, is_ref, refs);
314
 
315
   nouveau_pushbuf_space(push, 6 + (codec == PIPE_VIDEO_CODEC_MPEG4_AVC ? 9 : 7) + fence_extra + 2, num_refs, 0);
316
   nouveau_pushbuf_refn(push, bo_refs, num_refs);
317
 
318
   caps |= 0 << 16; // reset struct comm if flag is set
319
   caps |= 1 << 17; // enable watchdog
320
   caps |= 0 << 18; // do not report error to VP, so it can continue decoding what we have
321
   caps |= 0 << 19; // if enabled, use crypto crap?
322
   bsp += 0x100;
323
 
324
   str_bsp = (struct strparm_bsp *)bsp;
325
   memset(str_bsp, 0, 0x80);
326
   str_bsp->w0[0] = 16;
327
   str_bsp->w1[0] = 0x1;
328
   bsp += 0x100;
329
   /* Reserved for picparm_vp */
330
   bsp += 0x300;
331
   /* Reserved for comm */
332
#if !NVC0_DEBUG_FENCE
333
   memset(bsp, 0, 0x200);
334
#endif
335
   bsp += 0x200;
336
   for (i = 0; i < num_buffers; ++i) {
337
      memcpy(bsp, data[i], num_bytes[i]);
338
      bsp += num_bytes[i];
339
      str_bsp->w0[0] += num_bytes[i];
340
   }
341
 
342
   /* Append end sequence */
343
   *(uint32_t *)bsp = endmarker;
344
   bsp += 4;
345
   *(uint32_t *)bsp = 0x00000000;
346
   bsp += 4;
347
   *(uint32_t *)bsp = endmarker;
348
   bsp += 4;
349
   *(uint32_t *)bsp = 0x00000000;
350
 
351
   bsp_addr = bsp_bo->offset >> 8;
352
   inter_addr = inter_bo->offset >> 8;
353
 
354
#if NVC0_DEBUG_FENCE
355
   memset(dec->comm, 0, 0x200);
356
   comm_addr = (dec->fence_bo->offset + COMM_OFFSET) >> 8;
357
#else
358
   comm_addr = bsp_addr + (COMM_OFFSET>>8);
359
#endif
360
 
361
   BEGIN_NVC0(push, SUBC_BSP(0x700), 5);
362
   PUSH_DATA (push, caps); // 700 cmd
363
   PUSH_DATA (push, bsp_addr + 1); // 704 strparm_bsp
364
   PUSH_DATA (push, bsp_addr + 7); // 708 str addr
365
   PUSH_DATA (push, comm_addr); // 70c comm
366
   PUSH_DATA (push, comm_seq); // 710 seq
367
 
368
   if (codec != PIPE_VIDEO_CODEC_MPEG4_AVC) {
369
      u32 bitplane_addr;
370
 
371
      bitplane_addr = dec->bitplane_bo->offset >> 8;
372
 
373
      nvc0_decoder_inter_sizes(dec, 1, &slice_size, &bucket_size, &ring_size);
374
      BEGIN_NVC0(push, SUBC_BSP(0x400), 6);
375
      PUSH_DATA (push, bsp_addr); // 400 picparm addr
376
      PUSH_DATA (push, inter_addr); // 404 interparm addr
377
      PUSH_DATA (push, inter_addr + slice_size + bucket_size); // 408 interdata addr
378
      PUSH_DATA (push, ring_size << 8); // 40c interdata_size
379
      PUSH_DATA (push, bitplane_addr); // 410 BITPLANE_DATA
380
      PUSH_DATA (push, 0x400); // 414 BITPLANE_DATA_SIZE
381
   } else {
382
      nvc0_decoder_inter_sizes(dec, desc.h264->slice_count, &slice_size, &bucket_size, &ring_size);
383
      BEGIN_NVC0(push, SUBC_BSP(0x400), 8);
384
      PUSH_DATA (push, bsp_addr); // 400 picparm addr
385
      PUSH_DATA (push, inter_addr); // 404 interparm addr
386
      PUSH_DATA (push, slice_size << 8); // 408 interparm size?
387
      PUSH_DATA (push, inter_addr + slice_size + bucket_size); // 40c interdata addr
388
      PUSH_DATA (push, ring_size << 8); // 410 interdata size
389
      PUSH_DATA (push, inter_addr + slice_size); // 414 bucket?
390
      PUSH_DATA (push, bucket_size << 8); // 418 bucket size? unshifted..
391
      PUSH_DATA (push, 0); // 41c targets
392
      // TODO: Double check 414 / 418 with nvidia trace
393
   }
394
 
395
#if NVC0_DEBUG_FENCE
396
   BEGIN_NVC0(push, SUBC_BSP(0x240), 3);
397
   PUSH_DATAh(push, dec->fence_bo->offset);
398
   PUSH_DATA (push, dec->fence_bo->offset);
399
   PUSH_DATA (push, dec->fence_seq);
400
 
401
   BEGIN_NVC0(push, SUBC_BSP(0x300), 1);
402
   PUSH_DATA (push, 1);
403
   PUSH_KICK (push);
404
 
405
   {
406
      unsigned spin = 0;
407
      do {
408
         usleep(100);
409
         if ((spin++ & 0xff) == 0xff) {
410
            debug_printf("b%u: %u\n", dec->fence_seq, dec->fence_map[0]);
411
            dump_comm_bsp(dec->comm);
412
         }
413
      } while (dec->fence_seq > dec->fence_map[0]);
414
   }
415
 
416
   dump_comm_bsp(dec->comm);
417
   return dec->comm->status[comm_seq & 0xf];
418
#else
419
   BEGIN_NVC0(push, SUBC_BSP(0x300), 1);
420
   PUSH_DATA (push, 0);
421
   PUSH_KICK (push);
422
   return 2;
423
#endif
424
}